Подтвердить что ты не робот

Как отладить 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?

4b9b3361

Ответ 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);
 });