Читаем Выразительный JavaScript полностью

В данном случае для создания исключения мы использовали конструктор Error. Это стандартный конструктор, создающий объект со свойством message. В современных окружениях JavaScript экземпляры этого конструктора также собирают информацию о стеке вызовов, который был накоплен в момент выкидывания исключения – так называемое отслеживание стека (stack trace). Эта информация сохраняется в свойстве stack, и может помочь при разборе проблемы – она сообщает, в какой функции случилась проблема и какие другие функции привели к данному вызову.

Обратите внимание, что функция look полностью игнорирует возможность возникновения проблем в promptDirection. Это преимущество исключений – код, обрабатывающий ошибки, нужен только в том месте, где происходит ошибка, и там, где она обрабатывается. Промежуточные функции просто не обращают на это внимания.

Ну, почти.

<p>Подчищаем за исключениями</p>

Представьте следующую ситуацию: функция withContext желает удостовериться, что во время её выполнения переменная верхнего уровня context содержит специальное значение контекста. В конце выполнения функция восстанавливает прежнее значение переменной.

var context = null;

function withContext(newContext, body) {

  var oldContext = context;

  context = newContext;

  var result = body();

  context = oldContext;

  return result;

}

Что, если функция body выбросит исключение? В таком случае вызов withContext будет выброшен исключением из стека, и переменной context никогда не будет возвращено первоначальное значение.

Но у инструкции try есть ещё одна особенность. За ней может следовать блок finally, либо вместо catch, либо вместе с catch. Блок finally означает «выполнить код в любом случае после выполнения блока try». Если функции надо что-то подчистить, то подчищающий код нужно включать в блок finally.

function withContext(newContext, body) {

  var oldContext = context;

  context = newContext;

  try {

    return body();

  } finally {

    context = oldContext;

  }

}

Заметьте, что нам больше не нужно сохранять результат вызова body в отдельной переменной, чтобы вернуть его. Даже если мы возвращаемся из блока try, блок finally всё равно будет выполнен. Теперь мы можем безопасно сделать так:

try {

  withContext(5, function() {

    if (context < 10)

      throw new Error("Контекст слишком мал!");

  });

} catch (e) {

  console.log("Игнорируем: " + e);

}

// → Игнорируем: Error: Контекст слишком мал!

console.log(context);

// → null

Несмотря на то, что вызываемая из withContext функция «сломалась», сам по себе withContext по-прежнему подчищает значение переменной context.

<p>Выборочный отлов исключений</p>

Когда исключение доходит до низа стека и его никто не поймал, его обрабатывает окружение. Как именно – зависит от конкретного окружения. В браузерах описание ошибки выдаётся в консоль (она обычно доступна в меню «Инструменты» или «Разработка»).

Если речь идёт об ошибках или проблемах, которые программа не может обработать в принципе, допустимо просто пропустить такую ошибку. Необработанное исключение – разумный способ сообщить о проблеме в программе, и консоль в современных браузерах выдаст вам необходимую информацию о том, какие вызовы функций были в стеке в момент возникновения проблемы.

Если возникновение проблемы предсказуемо, программа не должна падать с необработанным исключением – это не очень дружественно по отношению к пользователю.

Недопустимое использование языка – ссылки на несуществующую переменную, запрос свойств у переменной, равной null, или вызов чего-то, что не является функцией – тоже приводит к выбрасыванию исключений. Такие исключения можно отлавливать точно так же, как свои собственные.

При входе в блок catch мы знаем только, что что-то внутри блока try привело к исключению. Мы не знаем, что именно, и какое исключение произошло.

JavaScript (что является вопиющим упущением) не предоставляет непосредственной поддержки выборочного отлова исключений: либо ловим все, либо никакие. Из-за этого люди часто предполагают, что случившееся исключение – именно то, ради которого и писался блок catch.

Но может быть и по-другому. Нарушение произошло где-то ещё, или в программу вкралась ошибка. Вот пример, где мы пробуем вызывать promptDirection до тех пор, пока не получим допустимый ответ:

for (;;) {

  try {

    var dir = promtDirection("Куда?"); // ← опечатка!

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных