Оператор throw
Оператор throw використовують для створення і викидання помилки, тобто для примусового переривання виконання коду та передачі керування в найближчий блок catch, якщо він є. Це основний спосіб повідомити про ситуацію, з якою функція не може коректно впоратися.
Теорія
TL;DR
throw вираз;негайно припиняє виконання поточної функції.- Далі JavaScript шукає найближчий
try...catch, щоб спіймати це значення. - Кинути можна будь-яке значення: рядок, число, об'єкт. Але правильний вибір це
Errorабо його підклас. - Підкласи
TypeError,ReferenceError,SyntaxError,RangeError,EvalErrorуточнюють природу проблеми. - Блок
finallyвиконується завжди, незалежно від того, чи була помилка.
Швидкий приклад
throw new Error("Щось пішло не так!");Коли інтерпретатор зустрічає throw, виконання поточної функції негайно припиняється, і JavaScript починає шукати найближчий блок try...catch, щоб спіймати цю помилку. Якщо такого блоку немає, помилка доходить до верху стека і програма (або поточна задача) падає.
Синтаксис і що саме можна кидати
throw вираз;Де вираз це будь-яке значення, але найчастіше це об'єкт помилки (Error).
Обробка через try...catch:
try {
throw new Error("Помилка з'єднання з сервером!");
} catch (error) {
console.log("Спіймали помилку:", error.message);
}Результат:
Спіймали помилку: Помилка з'єднання з сервером!
JavaScript не вимагає викидати саме об'єкт помилки, кинути можна що завгодно:
throw "Просто рядок";
throw 404;
throw { message: "Помилка даних", code: 123 };Але за стандартом краще завжди використовувати Error або його підкласи: лише вони гарантовано мають name, message і стек викликів.
Вбудовані типи помилок
Errorце базовий типTypeErrorReferenceErrorSyntaxErrorRangeErrorEvalError
Приклад з конкретним типом:
function divide(a, b) {
if (b === 0) {
throw new RangeError("Ділення на нуль!");
}
return a / b;
}
try {
divide(5, 0);
} catch (err) {
console.error(err.name + ": " + err.message);
}Результат:
RangeError: Ділення на нуль!
Обраний тип помилки дозволяє в catch розрізняти ситуації через err instanceof RangeError і реагувати по-різному.
Як це працює у зв'язці try...catch...finally
try {
console.log("Починаємо");
throw new Error("Помилка!");
} catch (e) {
console.log("Спіймали:", e.message);
} finally {
console.log("Цей блок виконається завжди");
}Результат:
Починаємо
Спіймали: Помилка!
Цей блок виконається завждиПідсумкова таблиця:
| Що робить | Опис |
|---|---|
throw | Перериває виконання і викидає помилку |
| Що можна викинути | Будь-яке значення (але рекомендований Error) |
| Чим обробляється | try...catch |
Після throw | Код у тому самому блоці не виконується |
Блок finally | Виконується завжди, навіть за throw |
Типові помилки
- Кидати рядок замість
Error. Уcatchтоді немає ніmessage, ніstack, а логи стають марними. Пишітьthrow new Error("..."). - Забувати
new.throw Error("...")теж працює, боErrorможна викликати безnew, а от власний клас помилки безnewповодитиметься не так, як очікується. - Очікувати, що код після
throwвиконається. Решта інструкцій у тому самому блоці недосяжна. - Ковтати помилку порожнім
catch. Блокcatch (e) {}приховує проблему; або обробіть її, або киньте далі черезthrow e. - Ставити
returnуfinally. Він перекриє і значення, що поверталося, і помилку, яку кидали, тож проблема тихо зникне. - Розраховувати, що
try...catchспіймає асинхронну помилку. Викид усерединіsetTimeoutабо в необробленому промісі поза цим блоком не ловиться: для промісів потрібніawaitуtryабо.catch().
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.