#node.js
#node.js #обещание #асинхронное ожидание #предупреждения #необработанное-исключение
Вопрос:
Node.js начиная с версии 7, синтаксический сахар async / await используется для обработки обещаний, и теперь в моем коде довольно часто появляется следующее предупреждение:
(node:11057) UnhandledPromiseRejectionWarning: Unhandled promise
rejection (rejection id: 1): ReferenceError: Error: Can't set headers
after they are sent.
(node:11057) DeprecationWarning: Unhandled promise rejections are
deprecated. In the future, promise rejections that are not handled
will terminate the Node.js process with a non-zero exit code.
К сожалению, нет ссылки на строку, в которой отсутствует catch .
Есть ли какой-нибудь способ найти его, не проверяя каждый блок try / catch?
Комментарии:
1. Вы могли бы использовать библиотеку Bluebird promise, и это, вероятно, дало бы вам трассировку стека.
2. Возможно, регистрация на
unhandledRejection
событие узла поможет? Смотрите Документы . Ваш обратный вызов получаетError
объект и фактическоеPromise
значение, и я полагаюError
, что объект может содержать трассировку стека.3. Если два предыдущих комментария не помогают, то
Can't set headers after they are sent.
должны дать вам подсказку, где в вашем коде это может произойти (т. Е. Где-то вы устанавливаете заголовки после того, как заголовки были бы уже отправлены — предположительно, из-за сбоя в понимании асинхронного кода, но это предположение)4. привет, что сообщения помогают точно определить, где в коде ошибка, кстати, это не так просто, как знать строку.
5. @jfriend00 Оказывается, это была ситуация, когда асинхронная функция выдавала ошибку — эти внутренние обещания узла для асинхронных функций никогда не используют Bluebird, поэтому наличие Bluebird не помогает в этом сценарии.
Ответ №1:
прослушивание unhandledRejection
события процесса.
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
// application specific logging, throwing an error, or other logic here
});
Комментарии:
1. Ведение
error.stack
журнала (или в приведенном выше примереreason.stack
) дает вам полную трассировку стека ошибки.2. Хотел бы я сказать, что это сработало, но это не так. Я на узле 8.9.4.
3. Я попробовал приведенный выше код и получил неопределенный как для reason, так и для p? Есть предложения? » Необработанное отклонение при: Обещание { состояние: ‘отклонено’, причина: не определено } причина: не определено »
4. Я добавил этот код в начало моего
app.js
файла узла, и, к сожалению, ничего не зарегистрировано. Узелv10.13.0
.5. Почему, черт возьми, это не часть поведения узла по умолчанию? Я нахожусь на версии 14.8.0, и он по-прежнему показывает совершенно бесполезные сообщения, даже когда я использую.
--trace-warnings
Ответ №2:
Правильный способ показать полную трассировку стека для необработанных отклонений обещаний ES6 — запустить Node.js с --trace-warnings
флагом. Это покажет полную трассировку стека для каждого предупреждения, без необходимости перехватывать отклонение из вашего собственного кода. Например:
узел --трассировка-предупреждения app.js
Убедитесь, что trace-warnings
флаг стоит перед именем вашего .js
файла! В противном случае флаг будет интерпретироваться как аргумент вашего скрипта, и он будет проигнорирован Node.js сама по себе.
Если вы хотите фактически обрабатывать необработанные отклонения (например, регистрируя их), то вместо этого вы можете использовать мой unhandled-rejection
модуль, который улавливает все необработанные отклонения для каждой основной реализации Promises, которая его поддерживает, с помощью одного обработчика событий.
Этот модуль поддерживает обещания Bluebird, ES6, Q, WhenJS, es6-promise
, then/promise
, и все, что соответствует любой из спецификаций необработанного отклонения (полная информация в документации).
Комментарии:
1. Используя узел 7.8.0, и все это дает мне трассировку стека для множества внутренних модулей узла. (узел: 10372) UnhandledPromiseRejectionWarning: отклонение необработанного обещания (идентификатор отклонения: 2): не определено при emitWarning (internal/process/promises.js:59:21) при отправке необработанных отказов (internal/process /promises.js:86:11) в процессе. _tickDomainCallback (internal/process/next_tick.js:136:7)
2. Я не вижу никакого вывода, который показывает, где проблема с необработанным обещанием.
3. Я добавил это в
package.json
start script, и, к сожалению, ничего не было зарегистрировано. Узелv10.13.0
.4. @user1063287 Убедитесь, что флаг находится в правильном месте в вашей команде. Я только что добавил обновление к ответу, чтобы подчеркнуть, что оно должно идти перед именем скрипта.
5. Вероятно, вы смотрите на трассировку стека предупреждения об устаревании, а не на исходную необработанную ошибку (которая должна быть где-то выше предупреждения об устаревании).
Ответ №3:
Ведение журнала с помощью трассировки стека
Если вы ищете более полезное сообщение об ошибке. Попробуйте добавить это в свой файл узла. Он должен отображать полную трассировку стека, где происходит сбой.
process.on('unhandledRejection', (error, p) => {
console.log('=== UNHANDLED REJECTION ===');
console.dir(error.stack);
});
Комментарии:
1. Единственное функциональное отличие заключается в создании console.dir в свойстве стека ошибки. Значительная разница в выводе по сравнению с принятым ответом.
2. Я пробовал это, но
error.stack
undefined
для меня. 🙁 узел v14.15.43. Это будет работать только тогда, когда ошибка является экземпляром ошибки. Это не сработает, если обещание будет отклонено, например, со строковым значением:
throw "Some error"
4. будет ли это работать, если не произойдет сбой?
DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Сейчас это не сбой, и я хочу исправить это, прежде чем у него появится шанс в будущем.
Ответ №4:
Этот модуль позволил мне отследить обещание (ы) виновника: https://www.npmjs.com/package/trace-unhandled
-
Установить
npm i trace-unhandled
-
Включить в код
require('trace-unhandled/register');
Комментарии:
1. Красиво, подключи и играй!
2. Узел 14.19.1: не помогло, все еще получаю
at emitUnhandledRejectionWarning (internal/process/promises.js:170:15)
(и это самое близкое, что я получаю к фактической строке)3. Спасибо за этот очень простой ответ. Через несколько часов найдено недостающее ожидание через 2 минуты после нахождения этого сообщения.
Ответ №5:
@Jeremy У меня был тот же результат, reason
переменная, предоставленная
process.on('unhandledRejection', (reason, p) => {});
не был определен, и мне требуется время, чтобы выяснить, что в моем коде были отклонения от обещаний, которые обычно ничего не дают:
new Promise((resolve reject) => {
const client = net.connect(options)
client.on("connect", () => {
resolve()
})
client.on("error", () => {
reject()
})
})
проблема в том, что у вас reject
ничего нет, чтобы получить трассировку, вы должны указать ошибку, например
new Promise((resolve reject) => {
const client = net.connect(options)
client.on("connect", () => {
resolve()
})
client.on("error", (err) => {
reject(err)
})
})
и если у вас нет ошибки, вы можете предоставить ее самостоятельно, даже если она пуста, это даст трассировку стека
reject(new Error())
Если вам нужно найти, откуда была вызвана ошибка, найдите в своем коде Promise
с пустым отклонением
Комментарии:
1. да, у меня буквально сотни асинхронных функций, и нет более быстрого способа найти его, чем попытаться отследить каждое отдельное место, где создается обещание, явно или неявно?