Баги и ошибки неизбежны в программировании. Тем не менее они могут раздражать и вызывать разочарование в работе. Предлагаем разобраться, что такое try / catch в JavaScript.
Что такое блок try/catch в JavaScript?
Блок try/catch в JavaScript используется для обработки ошибок. Он помогает избежать прерывание кода из-за ошибок в вашем скрипте.
Хотя это может показаться чем-то, что можно легко реализовать с помощью оператора if, try/catch предоставляет много преимуществ, которые выходят за рамки возможностей if/else, некоторые из которых мы рассмотрим ниже.
Оператор try позволяет проверить блок кода на наличие ошибок.
Оператор catch позволяет обработать эту ошибку. Например:
Вот как строится конструкция try/catch. Вы помещаете код в блок try, и если возникает ошибка, JavaScript передает управление оператору catch, который выполняет указанные действия. В данном случае он выводит ошибку в виде оповещения.
Все ошибки JavaScript на самом деле являются объектами, которые содержат два свойства: имя (например, Error, SyntaxError и т. д.) и само сообщение об ошибке. Поэтому, когда мы выводим e, мы получаем что-то вроде ReferenceError: getData is not defined.
Как и любой другой объект в JavaScript, вы можете решать, как получить значения по-разному, например, e.name (ReferenceError) и e.message (getData is not defined).
Но на самом деле это не отличается от того, что делает JavaScript. Хотя JavaScript уважает вас достаточно, чтобы записать ошибку в консоль, а не показывать оповещение всему миру.
Как использовать операторы try/catch
Оператор throw
Одно из преимуществ try/catch - это возможность отображать свои собственные пользовательские ошибки. Это называется throw error.
В ситуациях, когда вы не хотите видеть те ошибки, которые отображает JavaScript, вы можете бросить свою ошибку (исключение) с помощью оператора throw. Эта ошибка может быть строкой, булевым значением или объектом. И если возникает ошибка, оператор catch отобразит ту ошибку, которую вы выбросили.
Здорово, не правда ли? Но мы можем пойти дальше, создавая ошибку с помощью конструкторов ошибок JavaScript.
JavaScript в основном классифицирует ошибки на шесть групп:
- EvalError - ошибка, произошедшая в функции eval.
- RangeError - число вне диапазона, например, 1.toPrecision(500). Метод toPrecision дает числам десятичное значение, например, 1.000, и число не может иметь 500 таких значений.
- ReferenceError - использование переменной, которая не была объявлена.
- SyntaxError - ошибка синтаксиса при выполнении кода.
- TypeError - использование значения, выходящего за пределы ожидаемых типов, например, 1.toUpperCase().
- URIError - ошибка, если используются незаконные символы в функции URI.
Таким образом, мы можем легко выбросить ошибку, например, throw new Error("Привет"). В этом случае имя ошибки будет Error, а сообщение — Привет. Вы также можете создать свой собственный конструктор ошибки, например:
И вы можете использовать это везде с throw new CustomError("данные не определены").
Проверим конструкцию try/catch. Рассмотрим следующий пример:
Но когда вы попробуете это выполнить, даже с использованием оператора try, это все равно не сработает. Это потому, что в JavaScript существуют два основных типа ошибок (то, что я описал выше — синтаксическая ошибка и так далее — на самом деле не являются типами ошибок. Вы можете назвать их примерами ошибок): ошибки времени разбора (parse-time errors) и ошибки времени выполнения (runtime errors) или исключения.
Ошибки времени разбора — это ошибки, которые возникают в коде, когда движок не понимает код.
Например, в приведенном выше коде, JavaScript не понимает, что вы имеете в виду под {{}}, и из-за этого ваш try/catch здесь бесполезен (он не сработает).
С другой стороны, ошибки времени выполнения — это ошибки, которые возникают в корректном коде, и это именно те ошибки, которые try/catch сможет обработать.
Приведенный выше код является корректным, и try/catch корректно обработает ошибку.
Оператор finally
Оператор finally действует как нейтральная зона, базовая точка или финальная стадия для блока try/catch. С помощью finally вы говорите, что, независимо от того, что произойдет в блоке try/catch (ошибка или отсутствие ошибки), код в блоке finally должен выполниться. Например:
Вложенные блоки try
Вы также можете вкладывать блоки try, но, как и любое другое вложение в JavaScript (например, if, for и так далее), это может привести к громоздкости и ухудшению читаемости кода, поэтому я не рекомендую это делать. Но это только мое мнение.
Вложение блоков try дает вам преимущество использования одного блока catch для нескольких блоков try. Хотя вы можете написать блок catch для каждого try отдельно, вот пример:
В этом случае не будет ошибки во внешнем блоке try, так как с ним все в порядке. Ошибка возникает во внутреннем блоке try, и она уже обработана своим собственным блоком catch. Рассмотрим следующий пример:
Этот код работает немного иначе: ошибка возникает во внутреннем блоке try, который не содержит catch, но вместо этого имеет блок finally.
Обратите внимание, что блок try/catch можно записать тремя разными способами: try...catch, try...finally, try...catch...finally. Однако ошибка выбрасывается из внутреннего блока try.
Блок finally для этого внутреннего try выполнится в любом случае, потому что, как мы уже говорили, он работает, что бы ни произошло в блоке try/catch. И хотя во внешнем блоке try нет ошибки, управление все равно передается его блоку catch для регистрации ошибки. Более того, используется ошибка, созданная во внутреннем блоке try, потому что она произошла именно там.
Если бы мы создали ошибку для внешнего блока try, она все равно бы отобразила внутреннюю ошибку, если только внутренняя не поймает свою собственную ошибку.
Вы можете поэкспериментировать с кодом ниже, закомментировав внутренний блок catch.
Повторное выбрасывание ошибки (Rethrow Error)
Оператор catch ловит все ошибки, которые попадают в него, и иногда нам это не нужно. Например:
Предположим на секунду, что введенное число будет меньше 5 (цель использования "use strict" — указать, что код должен выполняться в строгом режиме). В строгом режиме, например, нельзя использовать необъявленные переменные.
Я хочу, чтобы оператор try выбросил ошибку "y не меньше 5", когда значение y больше 5, что маловероятно. Ошибка должна быть связана с тем, что y не меньше..., а не с тем, что y не определена.
В таких ситуациях вы можете проверить тип ошибки, и если это не та ошибка, которую вы хотите, повторно выбросить её:
Это просто повторно выбросит ошибку для другого оператора try или остановит выполнение скрипта. Это полезно, когда вы хотите отслеживать только определенный тип ошибок, а остальные, возникшие из-за невнимательности, должны остановить выполнение кода.