Книга: JavaScript. Подробное руководство, 6-е издание

5.6.6. Инструкция try/catch/finally

5.6.6. Инструкция try/catch/finally

Инструкция try/catch/finally реализует механизм обработки исключений в JavaScript. Конструкция try в этой инструкции просто определяет блок кода, в котором обрабатываются исключения. За блоком try следует конструкция catch с блоком инструкций, вызываемых, если где-либо в блоке try возникает исключение. За конструкцией catch следует блок finally, содержащий программный код, выполняющий заключительные операции, который гарантированно выполняется независимо от того, что происходит в блоке try. И блок catch, и блок finally не являются обязательными, однако после блока try должен обязательно присутствовать хотя бы один из них. Блоки try, catch и finally начинаются и заканчиваются фигурными скобками. Это обязательная часть синтаксиса, и она не может быть опущена, даже если между ними содержится только одна инструкция.

Следующий фрагмент иллюстрирует синтаксис и назначение инструкции try/catch/finally:

try {
  // Обычно этот код без сбоев работает от начала до конца.
  // Но в какой-то момент в нем может быть сгенерировано исключение
  // либо непосредственно с помощью инструкции throw, либо косвенно -
  // вызовом метода, генерирующего исключение.
}
catch (е) {
  // Инструкции в этом блоке выполняются тогда и только тогда, когда в блоке try
  // возникает исключение. Эти инструкции могут использовать локальную переменную е,
  // ссылающуюся на объект Error или на другое значение, указанное в инструкции throw.
  // Этот блок может либо некоторым образом обработать исключение, либо
  // проигнорировать его, делая что-то другое, либо заново сгенерировать
  // исключение с помощью инструкции throw.
}
finally {
  // Этот блок содержит инструкции, которые выполняются всегда, независимо от того,
  // что произошло в блоке try. Они выполняются, если блок try завершился:
  // 1) как обычно, достигнув конца блока
  // 2) из-за инструкции break, continue или return
  // 3) с исключением, обработанным приведенным в блоке catch выше
  // 4) с неперехваченным исключением, которое продолжает свое
  // распространение на более высокие уровни
}

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

Далее приводится более реалистичный пример инструкции try/catch. В нем вызываются метод factorial(), определенный в предыдущем разделе, и методы prompt() и alert() клиентского JavaScript для организации ввода и вывода:

try {
  // Запросить число у пользователя
  var n = Number(prompt("Введите положительное число",""));
  // Вычислить факториал числа, предполагая, что входные данные корректны
  var f = factorial(n);
  // Вывести результат
  alert(n + "! = " + f);
}
catch (ex) { // Если данные некорректны, управление будет передано сюда
  alert(ех); // Сообщить пользователю об ошибке
}

Это пример инструкции try/catch без конструкции finally. Хотя finally используется не так часто, как catch, тем не менее иногда эта конструкция оказывается полезной. Однако ее поведение требует дополнительных объяснений. Блок finally гарантированно исполняется, если исполнялась хотя бы какая-то часть блока try, независимо от того, каким образом завершилось выполнение программного кода в блоке try. Эта возможность обычно используется для выполнения заключительных операций после выполнения программного кода в предложении try.

В обычной ситуации управление доходит до конца блока try, а затем переходит к блоку finally, который выполняет необходимые заключительные операции. Если управление вышло из блока try как результат выполнения инструкций return, continue или break, перед передачей управления в другое место выполняется блок finally.

Если в блоке try возникает исключение и имеется соответствующий блок catch для его обработки, управление сначала передается в блок catch, а затем - в блок finally. Если отсутствует локальный блок catch, то управление сначала передается в блок finally, а затем переходит на ближайший внешний блок catch, который может обработать исключение.

Если сам блок finally передает управление с помощью инструкции return, continue, break или throw или путем вызова метода, генерирующего исключение, незаконченная команда на передачу управления отменяется и выполняется новая. Например, если блок finally сгенерирует исключение, это исключение заменит любое ранее сгенерированное исключение. Если в блоке finally имеется инструкция return, произойдет нормальный выход из метода, даже если генерировалось исключение, которое не было обработано.

Конструкции try и finally могут использоваться вместе без конструкции сatch. В этом случае блок finally - это просто набор инструкций, выполняющих заключительные операции, который будет гарантированно выполнен независимо от наличия в блоке try инструкции break, continue или return. Напомню, из-за различий в работе инструкции continue в разных циклах невозможно написать цикл while, полностью имитирующий работу цикла for. Однако если добавить инструкцию try/finally, можно написать цикл while, который будет действовать точно так же, как цикл for, и корректно обрабатывать инструкцию continue:

// Имитация цикла for( инициализация ; проверка ; инкремент ) тело цикла;
инициализация ;
while( проверка ) {
  try { тело цикла ; }
  finally { инкремент ; }
}

Обратите однако внимание, что тело цикла while, содержащее инструкцию break, будет вести себя несколько иначе (из-за выполнения лишней операции инкремента перед выходом), чем тело цикла for, поэтому даже используя конструкцию finally, невозможно точно сымитировать цикл for с помощью цикла while.

Оглавление книги


Генерация: 0.519. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз