Обработка ошибок в JavaScript строится на двух фундаментальных механизмах: синхронном и асинхронном. Синхронные ошибки возникают во время выполнения кода, а асинхронные — внутри промисов, таймеров или асинхронных функций. Основной целью обработки ошибок является предотвращение падения программы и корректная реакция на непредвиденные ситуации.
Все ошибки в JavaScript представляют собой объекты, производные от
базового класса Error.
Основные свойства объектов ошибок:
name — тип ошибки (например, TypeError,
ReferenceError).message — текстовое описание ошибки.stack — стек вызовов, полезный для отладки.Пример создания ошибки вручную:
throw new Error('Неверный формат данных');
Кроме базового класса Error, есть встроенные
специализированные классы ошибок:
SyntaxError — ошибка синтаксиса.ReferenceError — обращение к несуществующей
переменной.TypeError — некорректный тип данных.RangeError — выход за предел допустимого
диапазона.URIError — ошибки функций работы с URI.Основной инструмент для перехвата ошибок — конструкция
try...catch. Она позволяет выполнять код в блоке
try и перехватывать исключения в блоке
catch.
try {
let result = riskyFunction();
console.log(result);
} catch (error) {
console.error('Произошла ошибка:', error.message);
}
Ключевые моменты:
catch получает объект ошибки.catch без параметра в современных
версиях JS, но чаще требуется доступ к объекту ошибки.catch допускается любая логика обработки
ошибки, включая повторную генерацию исключения с
throw.Блок finally выполняется всегда,
независимо от того, произошла ошибка или нет. Он полезен для
освобождения ресурсов или завершения операций, которые должны
выполниться обязательно.
try {
openConnection();
processData();
} catch (error) {
console.error(error);
} finally {
closeConnection();
}
Создание пользовательских ошибок позволяет контролировать поведение приложения в специфических ситуациях.
function validateAge(age) {
if (age < 0 || age > 150) {
throw new RangeError('Возраст вне допустимого диапазона');
}
}
Можно создавать собственные классы ошибок, наследуя
Error:
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
throw new ValidationError('Неверное значение поля');
Асинхронные операции требуют отдельного подхода. Промисы и
async/await позволяют обрабатывать ошибки следующим
образом:
Через .catch() у промиса:
fetch('/data.json')
.then(response => response.json())
.catch(error => console.error('Ошибка запроса:', error));
Через try…catch в async-функции:
async function fetchData() {
try {
let response = await fetch('/data.json');
let data = await response.json();
console.log(data);
} catch (error) {
console.error('Ошибка при загрузке данных:', error);
}
}
Для перехвата необработанных исключений существуют глобальные обработчики:
window.onerror и
window.onunhandledrejection.process.on('uncaughtException') и
process.on('unhandledRejection').window.addEventListener('error', event => {
console.error('Глобальная ошибка:', event.message);
});
window.addEventListener('unhandledrejection', event => {
console.error('Необработанный промис:', event.reason);
});
Эти обработчики полезны для логирования ошибок и предотвращения полного сбоя приложения.
try...catch для контролируемого потока
выполнения. Он предназначен только для непредвиденных ситуаций.TypeError, RangeError) для лучшей
диагностики.try...catch вместе с
async/await или .catch() для промисов.Иногда обработка ошибки частичная, и её нужно передать выше по стеку
вызовов. Это делается через throw внутри блока
catch:
try {
processData();
} catch (error) {
logError(error);
throw error; // передача ошибки дальше
}
Перевыбрасывание позволяет комбинировать локальную обработку и глобальный контроль ошибок.
Обработка ошибок является фундаментальной частью устойчивого и поддерживаемого JavaScript-кода, обеспечивая безопасность и предсказуемость работы приложений.