Ошибки в JavaScript бывают неизбежны: некорректные данные, нестабильная сеть, неожиданные состояния. try/catch - базовый инструмент, чтобы контролировать ошибки и не “ронять” весь сценарий.
Главное: try/catch ловит ошибки внутри блока try и в момент выполнения. Для асинхронных ошибок нужен await или обработка через Promise.
1) Базовая форма try/catch
try {
const result = JSON.parse("{ bad json }");
console.log(result);
} catch (e) {
console.log(e.name);
console.log(e.message);
}
Если внутри try будет ошибка, управление перейдет в catch.
2) Что ловит try/catch
Он ловит:
- ошибки времени выполнения (ReferenceError, TypeError и т.д.)
- ошибки, которые бросаются через
throw
Пример:
try {
const a = null;
console.log(a.value);
} catch (e) {
console.log(e.name); // "TypeError"
}
3) throw: выбросить ошибку вручную
throw используется, когда нужно явно остановить выполнение и сообщить об ошибке.
function parseJSON(text) {
if (typeof text !== "string") {
throw new TypeError("text must be a string");
}
return JSON.parse(text);
}
try {
parseJSON(123);
} catch (e) {
console.log(e.name);
console.log(e.message);
}
4) finally: выполнится всегда
finally выполняется и при успехе, и при ошибке. Туда удобно помещать финальные действия: убрать индикатор загрузки, вернуть кнопку в активное состояние.
try {
console.log("start");
JSON.parse("{ bad json }");
} catch (e) {
console.log("error");
} finally {
console.log("finish");
}
5) try/catch не ловит ошибки Promise без await
Это частая ловушка. Ошибка в Promise появляется позже, и синхронный try/catch ее не поймает.
try {
Promise.reject(new Error("Fail"));
} catch (e) {
console.log("not caught");
}
Правильные варианты:
Вариант 1: catch у Promise
Promise.reject(new Error("Fail")).catch((e) => {
console.log(e.message);
});
Вариант 2: await внутри try/catch
async function run() {
try {
await Promise.reject(new Error("Fail"));
} catch (e) {
console.log(e.message);
}
}
run();
6) Обработка ошибок в async/await
Реальный шаблон: запрос, проверка статуса, парсинг JSON.
async function loadJSON(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error("HTTP " + response.status);
}
return response.json();
}
async function run() {
try {
const data = await loadJSON("/api/data");
console.log(data);
} catch (e) {
console.log(e.message);
}
}
run();
7) Делать сообщение об ошибке понятным
Ошибку можно логировать полностью:
try {
JSON.parse("{ bad json }");
} catch (e) {
console.log(e);
}
А можно выводить только важное:
try {
JSON.parse("{ bad json }");
} catch (e) {
console.log(e.name + ": " + e.message);
}
8) Что лучше не делать: глотать ошибки молча
Если catch пустой, ошибка исчезнет и отладка станет сложнее.
try {
JSON.parse("{ bad json }");
} catch (e) {}
Лучше хотя бы вывести сообщение:
try {
JSON.parse("{ bad json }");
} catch (e) {
console.log(e.message);
}
Что стоит запомнить
- try/catch ловит ошибки только во время выполнения кода в try.
- throw позволяет выбрасывать ошибки вручную.
- finally выполняется всегда, удобен для финальных действий.
- Для Promise try/catch работает только вместе с await.
- В async/await типовой шаблон:
try { await ... }catch { ... }.