Блоки try… catch… finally… в JScript 5. Javascript


Оглавление (нажмите, чтобы открыть):

Операторы перехода и обработка исключений

Веб-программирование — JavaScript — Операторы перехода и обработка исключений

Еще одной категорией операторов языка JavaScript являются операторы перехода. Как следует из названия, эти операторы заставляют интерпретатор JavaScript переходить в другое место в программном коде. Оператор break заставляет интерпретатор перейти в конец цикла или другой инструкции. Оператор continue заставляет интерпретатор пропустить оставшуюся часть тела цикла, перейти обратно в начало цикла и приступить к выполнению новой итерации. В языке JavaScript имеется возможность помечать инструкции именами, благодаря чему в операторах break и continue можно явно указывать, к какому циклу или к какой другой инструкции они относятся.

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

Подробнее все эти операторы перехода описываются в следующих подразделах.

Метки инструкций

Любая инструкция может быть помечена указанным перед ней идентификатором и двоеточием:

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

Присвоив имя циклу, его затем можно использовать в инструкциях break и continue, внутри цикла для выхода из него или для перехода в начало цикла, к следующей итерации. Инструкции break и continue являются единственными инструкциями в языке JavaScript, в которых можно указывать метки — о них подробнее рассказывается далее. Ниже приводится пример инструкции while с меткой и инструкции continue, использующей эту метку:

Идентификатор, используемый в качестве метки инструкции, может быть любым допустимым идентификатором JavaScript, кроме зарезервированного слова. Имена меток отделены от имен переменных и функций, поэтому в качестве меток допускается использовать идентификаторы, совпадающие с именами переменных или функций.

Метки инструкций определены только внутри инструкций, к которым они применяются (и, конечно же, внутри вложенных в них инструкций). Вложенные инструкции не могут помечаться теми же идентификаторами, что и вмещающие их инструкции, но две независимые инструкции могут помечаться одинаковыми метками. Помеченные инструкции могут помечаться повторно. То есть любая инструкция может иметь множество меток.

Оператор break

Оператор break приводит к немедленному выходу из самого внутреннего цикла или оператора switch. Ранее мы уже видели примеры использования оператора break внутри оператора switch. В циклах он обычно используется для немедленного выхода из цикла, когда по каким-либо причинам требуется завершить выполнение цикла.

Когда цикл имеет очень сложное условие завершения, зачастую проще бывает реализовать эти условия с помощью оператора break, чем пытаться выразить их в одном условном выражении цикла. Следующий пример пытается отыскать элемент массива с определенным значением. Цикл завершается обычным образом по достижении конца массива или с помощью оператора break, как только будет найдено искомое значение:

В языке JavaScript допускается указывать имя метки за ключевым словом break (идентификатор без двоеточия):

Когда оператор break используется с меткой, она выполняет переход в конец именованной инструкции или прекращение ее выполнения. В случае отсутствия инструкции с указанной меткой попытка использовать такую форму оператора break порождает синтаксическую ошибку. Именованная инструкция не обязана быть циклом или оператором switch. Оператор break с меткой может выполнять «выход» из любой вмещающей ее инструкции. Объемлющая инструкция может даже быть простым блоком инструкций, заключенным в фигурные скобки исключительно с целью пометить его.

Между ключевым словом break и именем метки не допускается вставлять символ перевода строки. Дело в том, что интерпретатор JavaScript автоматически вставляет пропущенные точки с запятой: если разбить строку программного кода между ключевым словом break и следующей за ним меткой, интерпретатор предположит, что имелась в виду простая форма этого оператора без метки, и добавит точку с запятой.

Оператор break с меткой необходим, только когда требуется прервать выполнение инструкции, не являющейся ближайшим объемлющим циклом или оператором switch.

Оператор continue

Оператор continue схож с оператором break. Однако вместо выхода из цикла оператор continue запускает новую итерацию цикла. Синтаксис оператора continue столь же прост, как и синтаксис оператора break. Оператор continue может также использоваться с меткой.

Оператор continue, как в форме без метки, так и с меткой, может использоваться только в теле цикла. Использование его в любых других местах приводит к синтаксической ошибке. Когда выполняется оператор continue, текущая итерация цикла прерывается и начинается следующая. Для разных типов циклов это означает разное:

В цикле while указанное в начале цикла выражение проверяется снова, и если оно равно true, тело цикла выполняется с начала.

В цикле do/while происходит переход в конец цикла, где перед повторным выполнением цикла снова проверяется условие.

В цикле for вычисляется выражение инкремента и снова вычисляется выражение проверки, чтобы определить, следует ли выполнять следующую итерацию.

В цикле for/in цикл начинается заново с присвоением указанной переменной имени следующего свойства.

Обратите внимание на различия в поведении оператора continue в циклах while и for. Цикл while возвращается непосредственно к своему условию, а цикл for сначала вычисляет выражение инкремента, а затем возвращается к условию. В следующем примере показано использование оператора continue без метки для выхода из текущей итерации цикла для четных чисел:

Оператор continue, как и break, может применяться во вложенных циклах в форме, включающей метку, и тогда заново запускаемым циклом необязательно будет цикл, непосредственно содержащий оператор continue. Кроме того, как и для break, переводы строк между ключевым словом continue и именем метки не допускаются.

Оператор return

Вызов функции является выражением и подобно всем выражениям имеет значение. Оператор return внутри функций служит для определения значения, возвращаемого функцией. Оператор return может располагаться только в теле функции. Присутствие его в любом другом месте является синтаксической ошибкой. Когда выполняется оператор return, функция возвращает значение выражения вызывающей программе. Например:

Если функция не имеет оператора return, при ее вызове интерпретатор будет выполнять инструкции в теле функции одну за другой, пока не достигнет конца функции, и затем вернет управление вызвавшей ее программе. В этом случае выражение вызова вернет значение undefined. Оператор return часто является последней инструкцией в функции, но это совершенно необязательно: функция вернет управление вызывающей программе, как только будет достигнут оператор return, даже если за ним следуют другие инструкции в теле функции.

Оператор return может также использоваться без выражения, тогда она просто прерывает выполнение функции и возвращает значение undefined вызывающей программе. Например:

Оператор throw

— это сигнал, указывающий на возникновение какой-либо исключительной ситуации или ошибки. — это способ просигнализировать о такой ошибке или исключительной ситуации. — значит обработать его, т.е. предпринять действия, необходимые или подходящие для восстановления после исключения.

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

Оператор throw имеет следующий синтаксис:

Результатом выражения может быть значение любого типа. Оператору throw можно передать число, представляющее код ошибки, или строку, содержащую текст сообщения об ошибке. Интерпретатор JavaScript возбуждает исключения, используя экземпляр класса Error одного из его подклассов, и вы также можете использовать подобный подход. Объект Error имеет свойство name, определяющее тип ошибки, и свойство message, содержащее строку, переданную функции-конструктору. Ниже приводится пример функции, которая возбуждает объект Error при вызове с недопустимым аргументом:

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

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

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

Конструкция try/catch/finally

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


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

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

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

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

Если пользователь введет отрицательное число, высветится предупреждающее сообщение:

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

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

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

Мастер Йода рекомендует:  Unity выпустила Visual Search, инструмент для управления 3D-ассетами с помощью ИИ

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

Перехват ошибок. Throw, Try и Catch

Оператор try позволяет проверить блок кода на возникновение ошибок.

Оператор catch позволяет обрабатывать возникшую ошибку.

Оператор throw позволяет генерировать пользовательские ошибки.

Оператор finally позволяет выполнять код после операторов try и catch не зависимо от результата.

Ошибки будут!

Во время выполнения кода JavaScript, могут возникать разные ошибки.

Это могут быть ошибки кодирования, сделанные программистом, ошибки, возникающие в результате ввода неверных данных, и другие непредвиденные вещи.

В следующем примере, чтобы умышленно создать ошибку, мы вместо команды alert написали adddlert:

JavaScript перехватит adddlert как ошибку и выполнит код в операторе catch, чтобы ее обработать.

Операторы try и catch

Оператор try определяет блок кода, который во время выполнения будет проверяться на возникновение ошибок.

Оператор catch определяет блок кода, который будет выполняться, если в блоке оператора try возникнет ошибка.

Операторы try и catch всегда используются в паре:

JavaScript генерирует ошибки

Когда возникает ошибка, обычно интерпретатор JavaScript останавливает выполнение кода и генерирует сообщение об ошибке.

Если говорить техническими терминами, то интерпретатор JavaScript сгенерирует исключение (сгенерирует ошибку).

На самом деле интерпретатор JavaScript создаст объект Error с двумя свойствами — name и message.

Оператор throw

Оператор throw позволяет создавать пользовательские ошибки.

В техническом смысле вы можете генерировать исключения (генерировать ошибки).

Исключения могут быть строкой, числом, логическим значением или объектом JavaScript:

Используя оператор throw вместе с try и catch, вы можете контролировать ход программы и генерировать пользовательские сообщения об ошибках.

Пример проверки ввода

В следующем примере проверяются данные ввода. Если введено неверное значение, то генерируется исключение (err).

Исключение (err) перехватывается оператором catch, и выводится пользовательское сообщение об ошибке:

HTML проверка

Приведенный выше код это всего лишь пример.

Современные браузеры часто используют комбинацию JavaScript и встроенной HTML проверки, реализуемой при помощи предопределенных правил, заданных в HTML атрибутах:

Оператор finally

Оператор finally позволяет выполнить код после операторов try и catch, независимо от результатов проверки:

Объект Error


В JavaScript есть встроенный объект Error, который предоставляет информацию по возникшей ошибке.

Объект Error предоставляет два полезных свойства:

Свойство Описание
name Устанавливает или возвращает имя ошибки
message Устанавливает или возвращает сообщение об ошибке (строку)

Значения свойства name

В свойстве name объекта Error может быть возвращено шесть различных значений:

Имя ошибки Описание
EvalError Ошибка в функции eval()
RangeError Число «за пределами диапазона»
ReferenceError Недопустимая ссылка (обращение)
SyntaxError Синтаксическая ошибка
TypeError Ошибка типов
URIError Ошибка в encodeURI()

EvalError

EvalError указывает на то, что возникла ошибка в функции eval().

В более новых версиях JavaScript никогда не генерируется ошибка EvalError. Вместо нее используется SyntaxError.

RangeError

Ошибка RangeError возникает, если вы используете число, которое выходит за пределы диапазона допустимых значений.

Например, нельзя задать число с 500 знаковыми цифрами.

ReferenceError

Ошибка ReferenceError возникает в том случае, когда вы используете (ссылаетесь) переменную, которая не была декларирована:

SyntaxError

Ошибка SyntaxError возникает, когда вы пытаетесь выполнить код с синтаксическими ошибками.

TypeError

Ошибка TypeError возникает, когда вы используете значение, выходящее за пределы диапазона ожидаемых типов:

URIError

Ошибка URIError возникает, когда вы используете недопустимые символы в функциях URI:

Нестандартные свойства объекта Error

Mozilla и Microsoft определяют ряд нестандартных свойств объекта Error:

fileName (Mozilla)
lineNumber (Mozilla)
columnNumber (Mozilla)
stack (Mozilla)
description (Microsoft)
number (Microsoft)

Никогда не используйте эти свойства в публичном веб-сайте. Они не будут работать во всех браузерах.

Error handling, «try..catch»

No matter how great we are at programming, sometimes our scripts have errors. They may occur because of our mistakes, an unexpected user input, an erroneous server response, and for a thousand other reasons.

Usually, a script “dies” (immediately stops) in case of an error, printing it to console.

But there’s a syntax construct try..catch that allows to “catch” errors and, instead of dying, do something more reasonable.

The “try…catch” syntax

The try..catch construct has two main blocks: try , and then catch :

It works like this:

  1. First, the code in try <. >is executed.
  2. If there were no errors, then catch(err) is ignored: the execution reaches the end of try and goes on, skipping catch .
  3. If an error occurs, then try execution is stopped, and the control flows to the beginning of catch(err) . The err variable (can use any name for it) will contain an error object with details about what happened.

So, an error inside the try <…>block does not kill the script: we have a chance to handle it in catch .

Let’s see examples.

An errorless example: shows alert (1) and (2) :

An example with an error: shows (1) and (3) :

For try..catch to work, the code must be runnable. In other words, it should be valid JavaScript.

It won’t work if the code is syntactically wrong, for instance it has unmatched curly braces:

The JavaScript engine first reads the code, and then runs it. The errors that occur on the reading phase are called “parse-time” errors and are unrecoverable (from inside that code). That’s because the engine can’t understand the code.

So, try..catch can only handle errors that occur in the valid code. Such errors are called “runtime errors” or, sometimes, “exceptions”.


If an exception happens in “scheduled” code, like in setTimeout , then try..catch won’t catch it:

That’s because the function itself is executed later, when the engine has already left the try..catch construct.

To catch an exception inside a scheduled function, try..catch must be inside that function:

Error object

When an error occurs, JavaScript generates an object containing the details about it. The object is then passed as an argument to catch :

For all built-in errors, the error object has two main properties:

name Error name. For instance, for an undefined variable that’s «ReferenceError» . message Textual message about error details.

There are other non-standard properties available in most environments. One of most widely used and supported is:

stack Current call stack: a string with information about the sequence of nested calls that led to the error. Used for debugging purposes.

Optional “catch” binding

If we don’t need error details, catch may omit it:

Using “try…catch”

Let’s explore a real-life use case of try..catch .

As we already know, JavaScript supports the JSON.parse(str) method to read JSON-encoded values.

Usually it’s used to decode data received over the network, from the server or another source.

We receive it and call JSON.parse like this:

You can find more detailed information about JSON in the JSON methods, toJSON chapter.

If json is malformed, JSON.parse generates an error, so the script “dies”.

Should we be satisfied with that? Of course not!

This way, if something’s wrong with the data, the visitor will never know that (unless they open the developer console). And people really don’t like when something “just dies” without any error message.

Let’s use try..catch to handle the error:

Here we use the catch block only to show the message, but we can do much more: send a new network request, suggest an alternative to the visitor, send information about the error to a logging facility, … . All much better than just dying.

Throwing our own errors

What if json is syntactically correct, but doesn’t have a required name property?

Here JSON.parse runs normally, but the absence of name is actually an error for us.

To unify error handling, we’ll use the throw operator.

“Throw” operator

The throw operator generates an error.

Technically, we can use anything as an error object. That may be even a primitive, like a number or a string, but it’s better to use objects, preferably with name and message properties (to stay somewhat compatible with built-in errors).

JavaScript has many built-in constructors for standard errors: Error , SyntaxError , ReferenceError , TypeError and others. We can use them to create error objects as well.

Their syntax is:

For built-in errors (not for any objects, just for errors), the name property is exactly the name of the constructor. And message is taken from the argument.

Let’s see what kind of error JSON.parse generates:

As we can see, that’s a SyntaxError .

And in our case, the absence of name is an error, as users must have a name .

So let’s throw it:

In the line (*) , the throw operator generates a SyntaxError with the given message , the same way as JavaScript would generate it itself. The execution of try immediately stops and the control flow jumps into catch .

Now catch became a single place for all error handling: both for JSON.parse and other cases.

Rethrowing

In the example above we use try..catch to handle incorrect data. But is it possible that another unexpected error occurs within the try <. >block? Like a programming error (variable is not defined) or something else, not just this “incorrect data” thing.

Of course, everything’s possible! Programmers do make mistakes. Even in open-source utilities used by millions for decades – suddenly a bug may be discovered that leads to terrible hacks.


In our case, try..catch is meant to catch “incorrect data” errors. But by its nature, catch gets all errors from try . Here it gets an unexpected error, but still shows the same «JSON Error» message. That’s wrong and also makes the code more difficult to debug.

Fortunately, we can find out which error we get, for instance from its name :

The rule is simple:

Catch should only process errors that it knows and “rethrow” all others.

The “rethrowing” technique can be explained in more detail as:

  1. Catch gets all errors.
  2. In the catch(err) <. >block we analyze the error object err .
  3. If we don’t know how to handle it, we do throw err .

In the code below, we use rethrowing so that catch only handles SyntaxError :

The error throwing on line (*) from inside catch block “falls out” of try..catch and can be either caught by an outer try..catch construct (if it exists), or it kills the script.

So the catch block actually handles only errors that it knows how to deal with and “skips” all others.

The example below demonstrates how such errors can be caught by one more level of try..catch :

Here readData only knows how to handle SyntaxError , while the outer try..catch knows how to handle everything.

try…catch…finally

Wait, that’s not all.

The try..catch construct may have one more code clause: finally .

If it exists, it runs in all cases:

  • after try , if there were no errors,
  • after catch , if there were errors.

The extended syntax looks like this:

Try running this code:

The code has two ways of execution:

  1. If you answer “Yes” to “Make an error?”, then try -> catch -> finally .
  2. If you say “No”, then try -> finally .

The finally clause is often used when we start doing something and want to finalize it in any case of outcome.

For instance, we want to measure the time that a Fibonacci numbers function fib(n) takes. Naturally, we can start measuring before it runs and finish afterwards. But what if there’s an error during the function call? In particular, the implementation of fib(n) in the code below returns an error for negative or non-integer numbers.

The finally clause is a great place to finish the measurements no matter what.

Here finally guarantees that the time will be measured correctly in both situations – in case of a successful execution of fib and in case of an error in it:

You can check by running the code with entering 35 into prompt – it executes normally, finally after try . And then enter -1 – there will be an immediate error, and the execution will take 0ms . Both measurements are done correctly.

In other words, the function may finish with return or throw , that doesn’t matter. The finally clause executes in both cases.

Please note that result and diff variables in the code above are declared before try..catch .

Otherwise, if we declared let in try block, it would only be visible inside of it.

The finally clause works for any exit from try..catch . That includes an explicit return .

In the example below, there’s a return in try . In this case, finally is executed just before the control returns to the outer code.

The try..finally construct, without catch clause, is also useful. We apply it when we don’t want to handle errors here (let them fall through), but want to be sure that processes that we started are finalized.

In the code above, an error inside try always falls out, because there’s no catch . But finally works before the execution flow leaves the function.

Global catch

The information from this section is not a part of the core JavaScript.

Let’s imagine we’ve got a fatal error outside of try..catch , and the script died. Like a programming error or some other terrible thing.

Is there a way to react on such occurrences? We may want to log the error, show something to the user (normally they don’t see error messages), etc.

There is none in the specification, but environments usually provide it, because it’s really useful. For instance, Node.js has process.on(«uncaughtException») for that. And in the browser we can assign a function to the special window.onerror property, that will run in case of an uncaught error.


The role of the global handler window.onerror is usually not to recover the script execution – that’s probably impossible in case of programming errors, but to send the error message to developers.

There are also web-services that provide error-logging for such cases, like https://errorception.com or https://www.muscula.com.

They work like this:

  1. We register at the service and get a piece of JS (or a script URL) from them to insert on pages.
  2. That JS script sets a custom window.onerror function.
  3. When an error occurs, it sends a network request about it to the service.
  4. We can log in to the service web interface and see errors.

Summary

The try..catch construct allows to handle runtime errors. It literally allows to “try” running the code and “catch” errors that may occur in it.

There may be no catch section or no finally , so shorter constructs try..catch and try..finally are also valid.

Error objects have following properties:

  • message – the human-readable error message.
  • name – the string with error name (error constructor name).
  • stack (non-standard, but well-supported) – the stack at the moment of error creation.

If an error object is not needed, we can omit it by using catch < instead of catch(err) < .

We can also generate our own errors using the throw operator. Technically, the argument of throw can be anything, but usually it’s an error object inheriting from the built-in Error class. More on extending errors in the next chapter.

Rethrowing is a very important pattern of error handling: a catch block usually expects and knows how to handle the particular error type, so it should rethrow errors it doesn’t know.

Перехват ошибок в JavaScript, «try..catch»

Перехват ошибок в JavaScript, «try..catch»

Здравствуйте! В этом уроке я хотел бы рассказать об ошибках в JavaScript и о том как их собственно обрабатывать. Ведь часто случается, что ошибки происходят время от времени и тут даже дело не в наличие опыта программирования или даже полном его отсутствии. Ведь и у матерых программистов тоже случаются ошибки никто от этого не застрахован.

Ошибки бывают в основном 2-х типов — это синтаксические и логические. К синтаксическим можно отнести ошибки в имени переменных, функций, ошибки в синтаксисе кода. В принципе такие ошибки легко отловить через консоль браузера.

А вот логические ошибки с ними все не так просто потому, что они приводят к неправильному выполнению кода программы. Поэтому для их устранения потребуется отладка программы, чтобы понять что собственно происходит на каждом шаге скрипта. Мы же с вами здесь рассмотрим в основном локализацию синтаксических ошибок с помощью конструкции try…catch.

Конструкция перехвата ошибок try…catch

Конструкция try..catch состит из 2-х блоков: try, и затем catch. Вот пример записи в общем виде

Работает эта конструкция таким образом:

  1. Выполняется код внутри блока try, так называемой ловушки.
  2. Если в нём не встречаются ошибки, то блок catch(err) игнорируется.
  3. А вот, если в нём возникнет ошибка, то выполнение try будет прервано на ошибке, и управление передается в начало блока catch(err). При этом переменная err (можно выбрать любое другое название) будет содержать объект ошибки с подробнейшей информацией о произошедшей ошибке.

Поэтому при ошибке в try скрипт не останавливается, и даже более того мы имеем возможность обработать ошибку внутри блока catch.

Рассмотрим это на примерах.

  • Пример без ошибок: при запуске сработают alert (1) и (2):

А вот пример с ошибкой: при запуске сработают (1) и (3):

В случае, если грубо нарушена структура кода, не закрыта фигурная скобка или где-то стоит лишняя запятая, то вам никакой try..catch не поможет. Это синтаксические ошибки, интерпретатор такой код просто не понимает.

Важное замечание try..catch может работать только в синхронном коде

Ошибку, которая может произойти в коде,который будет выполняться через время например в setTimeout, try..catch не поймает:

На момент запуска функции, назначенной через setTimeout, этот код уже завершится, и интерпретатор выйдет из блока try..catch.

Для того чтобы Чтобы поймать ошибку внутри функции из setTimeout, и try..catch должен быть в той же функции.

Объект ошибки

В примере выше мы видим объект ошибки, который вы передаете в блок catch. У него есть три основных свойства:

name Тип ошибки. Например, при обращении к переменной, которой нет: «ReferenceError». message Сообщение о деталях ошибки stack Выводит более полную информацию, с указанием строки, где произошла ошибка и саму ошибку.

Генерация своих ошибок

Оператор throw

Данный оператор throw генерирует ошибку.

Технически в качестве объекта ошибки вы можете передать что угодно, это может быть даже и не объект, а число или строка.


В качестве конструктора ошибок вы можете использовать встроенный конструктор: new Error(message) или любой другой.

В JavaScript также встроен ряд конструкторов для стандартных ошибок: SyntaxError, ReferenceError, RangeError и некоторые другие.

В данном примере мы используем конструктор new SyntaxError(message). Он создаёт ошибку того же типа, что и JSON.parse.

Получается, что блок catch – единственное место для обработки ошибок во всех случаях.

Оборачивание исключений

И, для полноты картины – последняя, техника по работе с ошибками. Она, является стандартной практикой во многих языках программирования.

Цель функции readData в примере выше – это прочитать данные. При этом чтении могут возникать различные ошибки, не только SyntaxError, но и, возможно, к примеру URIError и другие.

Код, который вызвает readData, хотел бы иметь конечно либо результат, либо информацию об ошибке.

При этом очень важным является следующий вопрос: обязан ли этот внешний код знать о типах ошибок, которые возникают при чтении данных, и конечно же уметь перехватывать их?

В данном случае, если при чтении данных происходит ошибка, то будем генерировать её в виде объекта ReadError, с сообщением. А «исходную» ошибку на всякий случай тоже сохраним, присвоим в свойство cause.

Выглядит это так:

Этот подход называют «оборачиванием» исключения, поскольку мы берём ошибки «более низкого уровня» и «заворачиваем» их в ReadError, которая соответствует текущей задаче.

Секция finally

В конструкции try..catch есть и ещё один блок: finally.

Выглядит этот расширенный синтаксис так:

Секция finally не обязательна, но если есть, то она будет выполнена всегда, независимо от того были ошибки или нет:

  • после блока try, в случае если ошибок не было,
  • после catch, в случае если они были.

Попробуйте запустить такой код?

У него 2 варианта работы:

  1. Если вы ответите на вопрос «сгенерировать ошибку?» утвердительно, то try -> catch -> finally.
  2. Если ответите отрицательно, то try -> finally.

Секцию finally используют, чтобы завершить начатые операции при любом варианте развития событий.

Последняя надежда: window.onerror

Допустим, ошибка произошла вне блока try..catch или выпала из try..catch наружу, во внешний код. Скрипт перестал работать.

Можно ли как-то узнать о том, что произошло? Да можно.

В браузере есть специальное свойство window.onerror, если в него записать функцию, то она выполнится и получит в аргументах сообщение ошибки, текущий URL и номер строки, откуда «выпала» ошибка.

Необходимо лишь позаботиться, чтобы функция была назначена заранее.

Как правило, роль window.onerror заключается не в том, чтобы оживить скрипт – скорее всего, это уже невозможно, а в том, чтобы отослать сообщение об ошибке на сервер, где разработчики о ней узнают.
Существуют даже специальные веб-сервисы, которые предоставляют скрипты для отлова и аналитики таких ошибок, например: https://errorception.com/ и https://www.muscula.com/.

Итого

Обработка ошибок – это очень полезная и важная тема.

В JavaScript для этого используют следующие методы:

  • Конструкция try..catch..finally – позволяет обработать ошибку в скрипте, как бы локализовать область с ошибкой.
  • Возможны также и другие варианты try..catch или try..finally.
  • Для генерации пользовательской ошибки используется оператор throw err.

Есть также и другие интересные приемы:

  • Проброс исключения – catch(err) обрабатывает только те ошибки, которые вы хотели бы в нём увидеть, а вот остальные – пробрасывать дальше через throw err. Определить, нужная ли это ошибка, можно, по свойству name.
  • Оборачивание исключений – эта некая функция, которая позволяет обернуть исключения и пробросить их дальше.
  • В window.onerror можно присвоить специальную функцию, которая выполнится при любой ошибке.


Задача

Сравните два фрагмента кода.

  1. Первый использует finally для выполнения кода по выходу из try..catch:

Второй фрагмент просто ставит очистку ресурсов за try..catch:

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

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Javascript error handling with try .. catch .. finally

I have a suspicion that I’m using the finally block incorrectly, and that I don’t understand the fundamentals of its purpose.

This function will run the catch block, alert «An error», but then return true. Why doesn’t it return false?

3 Answers 3

The finally block contains statements to execute after the try and catch blocks execute but before the statements following the try. catch statement. The finally block executes whether or not an exception is thrown. If an exception is thrown, the statements in the finally block execute even if no catch block handles the exception. more

The finally block will always run, try returning true after your try block

Finally blocks execute when you leave the try block. In your code this happens when you return false. That sets the return value to false and attempts to exit the function. But first it has to exit the try block which triggers the finally and overwrites the return value to true.

It is considered by many to be a good programming practice to have a single return statement per function. Consider making a var retval at the beginning of your function and setting it to true or false as appropriate throughout your function and then structuring the code so that it falls correctly through to a single return at the bottom.

Run this on your browser’s console and it might give you the answer you’re looking for.

JavaScript — Обработка исключений

На этом уроке мы познакомимся с оператором обработки исключений try. catch , который предназначен для перехвата ошибок в некотором блоке кода и их обработки.

Применение оператора try. catch

Оператор обработки исключений try. catch обычно применяется в следующих ситуациях:

  • Для некоторого участка кода, в котором может возникнуть ошибка;
  • Для валидации (проверки) данных перед отправкой на сервер;
  • Для использования в сложных случаях при написании кроссбраузерных приложений.

Теперь давайте рассмотрим, что же произойдет в сценарии на JavaScript при возникновении ошибки и для чего нужен оператор try. catch .

Если в сценарии на языке JavaScript появится ошибка, то дальнейшее выполнение программы будет прекращено. Т.е. инструкции (операторы), которые идут после ошибки выполняться не будут. Но если нам необходимо выполнение программы не прерывать, а переходить к следующей инструкции после той, где может возникнуть ошибка, то эту инструкцию необходимо заключить в оператор » try. catch «.

Синтаксис оператора try. catch

Принцип работы с оператором try. catch заключается в следующем:

Блок, в котором могут возникнуть ошибки, мы обрамляем фигурными скобками, и перед ним пишем ключевое слово try (с англ. попробовать). После этого блока пишем ключевое слово catch (с англ. поймать, ловить) и в круглых скобках указываем переменную, в которой будем хранить информацию об ошибке. Далее фигурными скобками обрамляем блок, предназначенный для обработки ошибок.

Принцип работы оператора try. catch

Оператор обработки исключений работает следующим образом:

Сначала он пытается выполнить все инструкции (операторы), указанные в блоке try . Если внутри блока try ошибки не возникает, то блок catch просто игнорируется, т.е. он не выполняется. В том случае если внутри блока try возникает ошибка, то оставшиеся операторы в этом блоке будут проигнорированы (т.е. они выполняться не будут) и сразу же начнут выполняться операторы внутри блока catch . Самое главное то, что инструкции, идущие после оператора try. catch , продолжат выполняться и работа программы не остановится.

В результате выполнения кода в 4 строчке произойдет ошибка, т.к. оператор documant браузером будет не определён. В этом случае 5 строчка браузером выполнена не будет, т.к. начнут выполняться операторы в блоке catch . В качестве параметра блока catch определим переменную e , в которой будет хранить информацию об ошибке. Данную переменную мы будем использовать в операторе alert для вывода сообщения об ошибке.

Блок finally

У оператора обработки исключений есть ещё один блок, который называется finally . Данный блок является не обязательным, и его можно использовать только при необходимости. Он не имеет параметров и в отличие от блока catch выполняется всегда, вне зависимости от того возникла ошибка или нет.

Но так как инструкции, идущие после оператора try. catch тоже выполняются всегда, то возникает вопрос: «Зачем нужен блок finally?»

На самом деле, инструкции, идущие после try. catch , выполняются не всегда. Это может произойти только в том случае, если произойдет ошибка в блоке catch . Когда это произойдёт, программа приостановит своё выполнение и операторы, идущие после конструкции try. catch выполняться не будут. Единственный блок инструкций (операторов), который будет выполняться – это блок finally .

В результате выполнения кода оператор alert , идущий после конструкции try. catch так и не будет выполнен.

Javascript try..catch?

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

Я увы мало работал с серверным JS, но когда разбирался с ним, а точнее выбирал между Erlang и Node.js мне на глаза попалась статья о том, что все в Node.js надо оборачивать в try/catch. Это связано с тем, что если что-то упадет, а ситуации бывают разные, то упадет и весь сервер. А вам это точно радости не прибавит.

Как в случае браузерного, так и в случае серверного Javascript конструкция try/catch используется для отлова исключений в синхронных операциях (пример: десериализация JSON-данных или валидация данных которые ввёл пользователь). Если требуется обрабатывать ошибки в асинхронных операциях, то ошибка либо передается в callback-функцию (В Node.js общепринятым шаблоном вызова callback-функции является вызов вида callback(err, results), где лишь один из аргументов может принимать значения отличные от null.), либо в более сложных случаях генерируется событие ‘error’ объекта класса EventEmitter.


В Node.js try/catch используется очень редко (в основном только при парсинге JSON-данных), это объясняется тем что большинство операций в Node.js асинхронны, как правило ошибку передают в callback-функцию или генерируют событие «error» у объекта класса EventEmitter.

Вот пример иллюстрирующий, что try/catch не отловит исключение возникшее при выполнении асинхронной операции:

Дело в том, что исключение бросается и, соответственно , должно ловиться в том контексте, в котором вызывается функция. В данном примере try/catch и вызов функции бросающей исключение выполнятся в разных контекстах в силу асинхронности функции doSomeAsynchronousOperation.

По поводу вашего последнего тезиса, обычно какие-то специфичные фичи, которых нету в браузерах, делают через $.support, модернизер ну или, например если нам надо проверить есть ли у браузера поддержка pushState, то просто if( window.history.pushState).

Но буквально недавно у меня была проблема с методом jQuery animate — scrollTop. в IE7 постоянно валились скрипты изза ошибки на уровне jQuery, и тут try/catch пришли на помощь.

Справочник по JScript : Конструкции JScript : Конструкция catch

Материал из WebWikiABCD

Содержание

try. catch. finally Statement — Конструкция try. catch. finally

Осуществляет обработку ошибок в JScript.

Синтаксис

Аргументы

Описание

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

Аргумент tryStatements содержат код, в котором может возникнуть ошибка, а catchStatements — код для обработки этих ошибок. При возникновении ошибки в tryStatements, управление программой передается catchStatements. Исходное значение exception — это значение возникшей в tryStatements ошибки. Если ошибок нет, то catchStatements не выполняется.

Если ошибка не может быть обработана в catchStatements, связанном с tryStatements где и произошла ошибка, используйте операторы throw или rethrow для трансляции ошибки на более высокий уровень обработчика ошибок.

После того, как выполнятся все операторы в tryStatements, и будет произведена обработка ошибок средствами catchStatements, будут выполняться операторы в finallyStatements.

Заметьте, что код в finallyStatements выполняется даже в том случае, если оператор возврата находится внутри блоков try или catch, или если блок catch перенаправляет ошибку. То есть операторы в блоке finallyStatements будут выполнены всегда, кроме случая, когда происходит не обрабатываемая ошибка (например, ошибка времени выполнения в блоке catch).

Примеры

В примерах показано как происходит обработка ошибок помощью конструкции try. catch. finally.

Справочник по JScript : Конструкции JScript : Конструкция catch

смотрим также

Материал из Справочник Web-языков

Содержание

try. catch. finally Statement — Конструкция try. catch. finally

Осуществляет обработку ошибок в JScript.

Синтаксис

Аргументы

Описание

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

Аргумент tryStatements содержат код, в котором может возникнуть ошибка, а catchStatements — код для обработки этих ошибок. При возникновении ошибки в tryStatements, управление программой передается catchStatements. Исходное значение exception — это значение возникшей в tryStatements ошибки. Если ошибок нет, то catchStatements не выполняется.

Если ошибка не может быть обработана в catchStatements, связанном с tryStatements где и произошла ошибка, используйте операторы throw или rethrow для трансляции ошибки на более высокий уровень обработчика ошибок.

После того, как выполнятся все операторы в tryStatements, и будет произведена обработка ошибок средствами catchStatements, будут выполняться операторы в finallyStatements.

Заметьте, что код в finallyStatements выполняется даже в том случае, если оператор возврата находится внутри блоков try или catch, или если блок catch перенаправляет ошибку. То есть операторы в блоке finallyStatements будут выполнены всегда, кроме случая, когда происходит не обрабатываемая ошибка (например, ошибка времени выполнения в блоке catch).

Примеры

В примерах показано как происходит обработка ошибок помощью конструкции try. catch. finally.

Блоки try … catch … finally … в JScript 5

Пояснення для людей, не знайомих з даною конструкцією

Конструкція try – catch – finally призначена для перехоплення помилок (виключень). Якщо в блоці try в якомусь операторі виникає помилка, JScript ігнорує інші оператори і переходить до блоку catch, де знаходиться блок обробки винятків. Останнім виконується блок finally, в якому зазвичай виконують деякі заключні дії. Допускається використання неповної конструкції – без catch або finally.

Скажу відразу, щоб не було ніяких непорозумінь: JScript – це JavaScript в інтерпретації Microsoft, а 5-я версія припускає наявність Internet Explorer 5.0 (в 4-м IE всього лише 3-я версія JScript).
Не знаю як ви, а я, скільки програмую на J [ava] Script, мріяв, щоб у цій мові з’явилася нарешті ця конструкція з двох слів, але йшли роки, а заповітні слова так і залишалися зарезервованими і я вже було втратив всяку надію, як вийшов п’ятий IE …

І ось, одного разу увечері, вносячи чергові зміни до свого JS Unix і порпаючись одночасно в нутрощах 5-го «зонда», погляд мій зачепив знайомі «try, catch» і незнайоме «Error». Неясна надія маленьким мерехтливим вогником загорілася в моїй душі. Обережно, не даючи їй згаснути, я простягнув руки до клавіатури, набрав try … catch … і в місце прикрого «зарезервовані слова» отримав радісне «передбачається наявність> «. Треба було бачити мене в той момент (або чути), каюсь: я кричав, що Гейтс молодчина. Каюсь, тому що Гейтс – поганий дядько, зробив в п’ятій версії те, що треба було зробити ще у першій. Ну да ладно, це все чудово, але треба було зробити так, щоб окрім п’ятого експлорера інші браузери не помічали цей блок. Добре, що в JScript є така чудова річ, як умовна компіляція. Скориставшись нею можна приховати все що завгодно від сторонніх очей Netscape Navigator і Internet Explorer 4.01 і нижче. Таким чином, вся конструкція виглядає так (після крапки з комою – мої коментарі):

Де Еrr – ім’я об’єкта Error, який буде створений при виникненні помилки, в нього будуть поміщені параметри помилки. Об’єкт Error має три конструктори і дві властивості:

Властивість (і параметр конструктора) number – числове значення (номер помилки), властивість description (також параметр конструктора) – рядок, опис помилки. Деякі числові значення та відповідні їм опису помилок наведено в таблиці нижче:































Номер помилки
Опис помилки
-2146823279 Визначення відсутнє
-2146827282 Передбачається наявність «)»
-2146827273 Незавершена рядкова константа
-2146827286 Помилка синтаксису
-2146827280 Передбачається наявність <
-2146827850 Об’єкт не підтримує це властивість чи метод
-2146827843 Команда не підтримується об’єктом
-2146827859 Неможливо створення об’єкта сервером програмування об’єктів
-2146828235 Файл не знайдено

Існує спосіб програмно порушити виняток (створити помилку) – досить викликати оператор throw зі створеним раніше об’єктом Error. При перехопленні помилки конструкцією try-catch створений об’єкт буде переданий блоку catch. Приклади:

Таким чином, JScript поповнився ще однією корисною конструкцією, істотно спрощує життя програміста.

Добавить комментарий