Поиск…
Синтаксис
- try {...} catch (ошибка) {...}
- попробуйте {...} наконец {...}
- try {...} catch (ошибка) {...} finally {...}
- throw new Error ([сообщение]);
- throw Error ([сообщение]);
замечания
try
указать блок кода, который будет проверяться на наличие ошибок во время его выполнения.
catch
позволяет вам определить блок кода, который должен быть выполнен, если в блоке try
произошла ошибка.
finally
позволяет выполнять код независимо от результата. Остерегайтесь, однако, инструкции потока управления блоков try и catch будут приостановлены до тех пор, пока выполнение окончательного блока не завершится.
Взаимодействие с обещаниями
Исключение является синхронной кодой , что отказы должны пообещать -асинхронный код. Если в обработчике обещаний выбрано исключение, его ошибка будет автоматически захвачена и использована вместо отклонения обещания.
Promise.resolve(5)
.then(result => {
throw new Error("I don't like five");
})
.then(result => {
console.info("Promise resolved: " + result);
})
.catch(error => {
console.error("Promise rejected: " + error);
});
Promise rejected: Error: I don't like five
Предложение асинхронных функций, которое, как ожидается, является частью ECMAScript 2017, расширяет его в противоположном направлении. Если вы ожидаете отклоненного обещания, его ошибка возникает как исключение:
async function main() {
try {
await Promise.reject(new Error("Invalid something"));
} catch (error) {
console.log("Caught error: " + error);
}
}
main();
Caught error: Invalid something
Объекты ошибок
Ошибки выполнения в JavaScript являются экземплярами объекта Error
. Объект Error
также может использоваться как-is или в качестве базы для пользовательских исключений. Можно выбросить любой тип значения - например, строки, но вам настоятельно рекомендуется использовать Error
или один из его производных, чтобы гарантировать, что отладочная информация, такая как трассировка стека, будет правильно сохранена.
Первым параметром конструктора Error
является сообщение с возможностью чтения человеком. Вам следует попытаться всегда указать полезное сообщение об ошибке, которое пошло не так, даже если дополнительную информацию можно найти в другом месте.
try {
throw new Error('Useful message');
} catch (error) {
console.log('Something went wrong! ' + error.message);
}
Порядок действий плюс продвинутые мысли
Без блока catch try неопределенные функции будут вызывать ошибки и останавливать выполнение:
undefinedFunction("This will not get executed");
console.log("I will never run because of the uncaught error!");
Выбросит ошибку и не запустит вторую строку:
// Uncaught ReferenceError: undefinedFunction is not defined
Вам нужен блок catch try, похожий на другие языки, чтобы вы могли поймать эту ошибку, чтобы код продолжал выполнять:
try {
undefinedFunction("This will not get executed");
} catch(error) {
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I will run because we caught the error!");
Теперь мы поймали ошибку и можем быть уверены, что наш код будет выполнен
// An error occured! ReferenceError: undefinedFunction is not defined(…)
// The code-block has finished
// I will run because we caught the error!
Что делать, если в нашем блоке catch произошла ошибка !?
try {
undefinedFunction("This will not get executed");
} catch(error) {
otherUndefinedFunction("Uh oh... ");
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I won't run because of the uncaught error in the catch block!");
Мы не будем обрабатывать остальную часть нашего блока catch, и выполнение остановится, за исключением блока finally.
// The code-block has finished
// Uncaught ReferenceError: otherUndefinedFunction is not defined(…)
Вы всегда можете вложить свои блоки захвата попыток ... но вы не должны, потому что это будет крайне беспорядочно.
try {
undefinedFunction("This will not get executed");
} catch(error) {
try {
otherUndefinedFunction("Uh oh... ");
} catch(error2) {
console.log("Too much nesting is bad for my heart and soul...");
}
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I will run because we caught the error!");
Уловит все ошибки из предыдущего примера и занесет в журнал следующее:
//Too much nesting is bad for my heart and soul...
//An error occured! ReferenceError: undefinedFunction is not defined(…)
//The code-block has finished
//I will run because we caught the error!
Итак, как мы можем поймать все ошибки !? Для неопределенных переменных и функций: вы не можете.
Кроме того, вы не должны обертывать каждую переменную и функцию в блок try / catch, потому что это простые примеры, которые будут возникать только один раз, пока вы их не исправите. Тем не менее, для объектов, функций и других переменных, которые, как вы знаете, существуют, но вы не знаете, будут ли их свойства или подпроцессы или побочные эффекты существовать, или вы ожидаете некоторых состояний ошибки в некоторых случаях, вы должны абстрагировать обработку ошибок каким-то образом. Вот очень простой пример и реализация.
Без защищенного способа вызова ненадежных методов или методов исключения:
function foo(a, b, c) {
console.log(a, b, c);
throw new Error("custom error!");
}
try {
foo(1, 2, 3);
} catch(e) {
try {
foo(4, 5, 6);
} catch(e2) {
console.log("We had to nest because there's currently no other way...");
}
console.log(e);
}
// 1 2 3
// 4 5 6
// We had to nest because there's currently no other way...
// Error: custom error!(…)
И с защитой:
function foo(a, b, c) {
console.log(a, b, c);
throw new Error("custom error!");
}
function protectedFunction(fn, ...args) {
try {
fn.apply(this, args);
} catch (e) {
console.log("caught error: " + e.name + " -> " + e.message);
}
}
protectedFunction(foo, 1, 2, 3);
protectedFunction(foo, 4, 5, 6);
// 1 2 3
// caught error: Error -> custom error!
// 4 5 6
// caught error: Error -> custom error!
Мы ломаем ошибки и все еще обрабатываем весь ожидаемый код, хотя и с несколько иным синтаксисом. В любом случае это сработает, но по мере создания более продвинутых приложений вы захотите начать думать о способах абстрагирования обработки ошибок.
Типы ошибок
В JavaScript существует шесть конкретных конструкторов ошибок ядра:
EvalError
- создает экземпляр, представляющий ошибку, возникающую в отношении глобальной функцииeval()
.InternalError
- создает экземпляр, представляющий ошибку, возникающую при возникновении внутренней ошибки в JavaScript-движке. Например, «слишком много рекурсии». (Поддерживается только Mozilla Firefox )RangeError
- создает экземпляр, представляющий ошибку, которая возникает, когда числовая переменная или параметр находится за пределами допустимого диапазона.ReferenceError
- создает экземпляр, представляющий ошибку, возникающую при разыменовании недопустимой ссылки.SyntaxError
- создает экземпляр, представляющий синтаксическую ошибку, возникающую при анализе кода вeval()
.TypeError
- создает экземпляр, представляющий ошибку, которая возникает, когда переменная или параметр не имеют допустимого типа.URIError
- создает экземпляр, представляющий ошибку, которая возникает, когдаencodeURI()
илиdecodeURI()
передаются недопустимые параметры.
Если вы внедряете механизм обработки ошибок, вы можете проверить, какой вид ошибки вы вылавливаете из кода.
try {
throw new TypeError();
}
catch (e){
if(e instanceof Error){
console.log('instance of general Error constructor');
}
if(e instanceof TypeError) {
console.log('type error');
}
}
В таком случае e
будет экземпляром TypeError
. Все типы ошибок расширяют базовую конструкцию Error
, поэтому она также является экземпляром Error
.
Помня об этом, мы видим, что проверка e
на случай Error
в большинстве случаев бесполезна.