Загрузка…
Загрузка…
Node.js · middle · сложность 4
Как опытный технический интервьюер и преподаватель, я часто сталкиваюсь с вопросами о надежной обработке ошибок в Node.js. Это важная тема для создания надежных приложений. Давайте сломаем
process.on('uncaughtException')
и
process.on('unhandledRejection')
.
uncaughtException
против.
unhandledRejection
Node.js, будучи асинхронным и управляемым событиями, имеет специальные механизмы для обработки ошибок, которые не обнаруживаются явно вашим кодом. Двумя основными глобальными обработчиками ошибок являются
process.on('uncaughtException')
и
process.on('unhandledRejection')
. Хотя оба имеют дело с необработанными ошибками, они возникают из-за разных типов операций и подразумевают разные уровни стабильности системы.
process.on('uncaughtException')
Что это такое: Ан
uncaughtException
возникает, когда во время выполнения вашей программы возникает синхронная ошибка (исключение), которая не перехватывается никем.
try...catch
блокировать. Обычно это указывает на серьезную ошибку в вашем коде или фундаментальную проблему в логике вашего приложения.
Аналогия: Представьте себе занятого повара (
Node.js application
) работаю на кухне. Вдруг повар случайно роняет острый нож(
throws an error
). Если нет подстраховки и того, кто ее поймает (
try...catch
), нож лязгает об пол, потенциально повреждая что-то или раня кого-то. Работа кухни теперь нарушена, и продолжать работу небезопасно.
Когда он излучается: Когда создается объект ошибки JavaScript (например,
throw new Error('Something went wrong!')
) и нет
try...catch
блок выше в стеке вызовов перехватывает его. Это относится к синхронным путям кода.
Последствия: Когда
uncaughtException
происходит, процесс Node.js считается находящимся в нестабильном и потенциально поврежденном состоянии. Это связано с тем, что ошибка могла произойти в любой момент, что потенциально может привести к тому, что переменные останутся в несогласованном состоянии, соединения с базой данных будут полуоткрытыми или данные будут записаны частично. **В документации Node.js настоятельно рекомендуется завершить процесс сразу после
uncaughtException
**. Продолжение выполнения может привести к непредсказуемому поведению, утечкам памяти или повреждению данных.
Пример кода:
// Register the uncaughtException handler early in your application lifecycle
process.on('uncaughtException', (err) => {
console.error('❌ FATAL: Uncaught Exception! The application is in an unstable state.');
console.error('Error details:', err.message);
console.error('Stack trace:', err.stack);
// Log the error details to a centralized logging service (e.g., Sentry, Splunk, ELK stack)
// Perform synchronous cleanup if absolutely critical (e.g., flush logs), but be quick!
// CRUCIAL: Terminate the process with a non-zero exit code (indicating an error)
// This allows process managers (like PM2, Docker, Kubernetes) to restart the service.
process.exit(1);
});
// --- Example of code that would trigger an uncaughtException ---
// 1. A synchronous error not wrapped in try-catch
console.log('Starting synchronous task...');
// This will throw an error that is not caught
// const data = JSON.parse('{"invalid json"'); // Uncomment to test
// 2. An error thrown inside a setTimeout (which makes the callback asynchronous,
// but the `throw` inside it is synchronous relative to the callback's execution)
setTimeout(() => {
console.log('Executing asynchronous task that throws sync error...');
throw new Error('This is an uncaught synchronous error from a setTimeout callback!');
}, 1000);
console.log('Application running. Waiting for errors...');process.on('unhandledRejection')
Что это такое: Ан
unhandledRejection
происходит, когда Обещание отклонено (т. е. оно не выполнено), но **нет
.catch()
обработчик** (или второй аргумент
.then()
), прикрепленный к этому Обещанию, для рассмотрения отказа. Это указывает на то, что асинхронная операция завершилась неудачно, и ваш код не учел ее сбой.
Аналогия: Представьте себе шеф-повара (
Node.js application
) принимает заказ на специальное блюдо (
Promise
). Готовя его, они понимают, что у них закончился ключевой ингредиент (
Promise rejects
). Если никто не сообщает клиенту(
no .catch()
), клиент остается ждать неопределенное время, или заказ просто исчезает из системы, и никто не узнает, что он не выполнен. Остальная часть кухни, возможно, еще сможет работать, но этот конкретный порядок проблематичен.
Когда он излучается: Когда объект Promise отклоняется (например,
Promise.reject(new Error('Failed!'))
или
async
функция выдает ошибку), и к ней не подключен механизм обработки ошибок до того, как цикл событий Node.js пройдет еще один тик.
Последствия: Исторически,
unhandledRejection
события не завершили процесс Node.js, а вместо этого выдали предупреждение. Однако ситуация меняется. В будущих версиях Node.js необработанные отклонения будут завершать процесс по умолчанию (аналогично
uncaughtException
), поскольку они часто представляют собой критические ошибки, при которых ожидаемая асинхронная операция завершилась неудачно без надлежащего отката. Поэтому **настоятельно рекомендуется лечить
unhandledRejection
в качестве серьезного предупреждения и рассмотрите возможность завершения процесса** для производственных приложений, чтобы избежать незначительных ошибок или неожиданного поведения.
Пример кода:
// Зарегистрируйте обработчик unhandledRejection на ранней стадии жизненного цикла приложения
process.on('unhandledRejection', (причина, обещание) => {
console.error('⚠️ ВНИМАНИЕ: необработанное отклонение обещания! Это указывает на отсутствие блока .catch().');
console.error('Причина:', причина);
console.error('Обещание:', обещание);
// Записываем сведения об ошибке в централизованную службу журналирования.
// Для критически важных приложений вам все равно может потребоваться корректное завершение работы здесь.
// процесс.выход(1); // Раскомментируйте это для производственных приложений
});
// --- Пример кода, вызывающего unhandledRejection ---
// 1. Промис, который отклоняется без обработчика .catch()
## Итог
Ключевой вывод для интервью: обсудите различия между слушателями `process.on('uncaughtException')` и `process.on('unhandledRejection')`. Когда