Как отладить javascript promises?
Я пытаюсь понять, как отлаживать асинхронный код, основанный на promises. Под Promises я имею в виду ECMAScript 6 на основе Promises и отлаживанием я имею в виду использование встроенного хром или отладчика firefox.
У меня возникают проблемы с тем, что при возникновении ошибки я не могу получить трассировку стека независимо от того, как я ее отклоняю.
Я пробовал:
console.log(new Error('Error occured'));
throw new Error('Throwing an Error');
return new Error('Error returned by the onRejected function');
reject(new Error('Pass Error to the reject function'));
Но ни одна из них не возвращает фактическую ошибку в коде или трассировку стека.
Итак, мой вопрос: как правильно отладить javascript Promises?
Ответы
Ответ 1
Это отличная тема для обсуждения, печальная новость заключается в том, что на самом деле это довольно сложно с native promises.
Отладка исходного ES6 promises в Chrome ужасна. Это связано с тем, что они будут молча подавлять ошибки и всякий раз, когда вы опускаете улов, это не даст вам никаких указаний на то, что обещание не удалось. Обновление: Chrome теперь регистрирует необработанные отклонения (см. Это ссылка на то, как)
Promise.resolve("foo").then(function(){
throw new Error("You will never see this");// silent failure
});
В Firefox все немного лучше, так как они выполняют необработанное обнаружение отклонений - однако это все еще непрозрачно, и если вы назначили обещание в любом месте, он не будет работать.
Итак, что можно сделать?
Включить Bluebird - это надмножество ES6 promises, и вы можете поменять его прямо внутри, он имеет богатый API, он быстрее и у него потрясающий стека. Он построен с учетом отладки и включает в себя отличные средства обработки ошибок.
После включения Bluebird вызовите:
Promise.longStackTraces();
Это немного замедлит работу (это будет очень быстро) и даст вам потрясающие сообщения об ошибках. Например:
Promise.resolve().then(function outer() {
return Promise.resolve().then(function inner() {
return Promise.resolve().then(function evenMoreInner() {
a.b.c.d()
});
});
});
В native promises - это будет тихий сбой и будет очень сложно отладить - с Bluebird promises это приведет к большой красной ошибке в консоли по умолчанию, предоставив вам:
ReferenceError: a is not defined
at evenMoreInner (<anonymous>:6:13)
From previous event:
at inner (<anonymous>:5:24)
From previous event:
at outer (<anonymous>:4:20)
From previous event:
at <anonymous>:3:9
at Object.InjectedScript._evaluateOn (<anonymous>:581:39)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:540:52)
at Object.InjectedScript.evaluate (<anonymous>:459:21)
Как только вы закончите отладку - вы можете поменять ее и вернуться к исходному promises. Лично я ценю знание, что у меня есть ошибки в производстве, поэтому я не рекомендую его, но это, безусловно, возможно.
Ответ 2
* Это не дает прямого ответа на ваш вопрос, но, тем не менее, может быть полезным.
Недавно Chrome devtools получил новую функцию, полезную для отладки асинхронного кода, например Promises.
http://www.html5rocks.com/en/tutorials/developertools/async-call-stack/
В принципе, включите флажок "асинхронный" на вкладке источников, и Chrome восстановит стек вызовов для вас, как если бы это был синхронный код.
![Снимок экрана]()
Ответ 3
Этот ответ является дополнением к Бенджамину Грюнбауму:
Если вы используете оператор catch в цепочке обещаний, вы получите трассировку стека error.stack:
Promise.longStackTraces();
function outer() {
return Promise.resolve();
}
function inner() {
return Promise.resolve();
}
function evenMoreInner() {
a.b.c.d()
}
Promise.resolve()
.then(outer)
.then(inner)
.then(evenMoreInner())
.catch(function (err) {
console.log(err.message);
console.log(err.stack);
});
Сообщение об ошибке:
ReferenceError: a is not defined
at evenMoreInner (test/test_promise.js:58:17) <<<< HERE the error!
at Context.<anonymous> (test/test_promise.js:64:23)
Ответ 4
Они, похоже, работают с инструментами отладки в Chrome. См. Эту тему для получения дополнительной информации.
https://code.google.com/p/v8/issues/detail?id=3093
Я не проверял, что это уже в версии dev или бета-версии, но я надеюсь, что это будет скоро. Тогда он может быть включен в обычную версию в январе 2015 года или около того (просто личная догадка, безусловное безусловное обещание, поскольку я даже не работаю в Google).
Ответ 5
Лучший способ отладки - это прослушать unhandledRejection
событие вашего process
.
Например, вот как вы можете настроить его и выгрузить трассировку стека...
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
// Stack Trace
console.log(reason.stack);
});