Как отлаживать обещания javascript?


Я пытаюсь понять, как отлаживать асинхронный код, основанный на обещаниях. Под обещаниями я подразумеваю обещания на основе ECMAScript 6, а под отладкой я имею в виду использование встроенного отладчика chrome или 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?

6 61

6 ответов:

Это отличная тема для обсуждения, печальные новости это на самом деле довольно трудно с родными обещаниями.

отладка raw ES6 обещает в Chrome ужасно. Это потому, что они будут молча подавлять ошибки, и всякий раз, когда вы опускаете улов, он не даст вам никаких признаков того, что обещание не удалось. обновление: Chrome теперь регистрирует необработанные отклонения (см. Эту ссылку для how)

 Promise.resolve("foo").then(function(){
      throw new Error("You will never see this");// silent failure
 });

в Firefox все немного лучше, так как они выполните необработанное обнаружение отклонения-однако, это все еще flakey, и если вы назначили обещание в любом месте, оно не будет работать.

Итак, что же можно сделать?

включить птица - это надмножество обещаний ES6, и вы можете поменять его прямо внутри, у него есть более богатый 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)

как только вы закончите отладку - вы можете поменять его и вернуться к родным обещаниям. Лично я ценю, зная, что у меня есть ошибки в производстве, поэтому я не рекомендую его, но это, безусловно, выполнимо.

*это не дает прямого ответа на ваш вопрос, но тем не менее может быть полезно.

Chrome devtools недавно получил новую функцию, которая полезна для отладки асинхронного кода, например Promises.

http://www.html5rocks.com/en/tutorials/developertools/async-call-stack/

в принципе, включите флажок" асинхронный "на вкладке "Источники", и Chrome восстановит стек вызовов для вас, как если бы он был синхронным код.

Screenshot

этот ответ является дополнением к ответу Бенджамина Грюнбаума: Если вы используете оператор catch в цепочке обещаний, вы получите трассировку стека по ошибка.стек:

        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's the error!
at Context.<anonymous> (test/test_promise.js:64:23)

Они, кажется, работают с инструментами отладки в Chrome. См. эту тему для получения дополнительной информации.

https://code.google.com/p/v8/issues/detail?id=3093

Я не проверял, если это уже в версии dev или бета-версии, но я надеюсь, что это будет в ближайшее время. Затем он может быть включен в обычную версию в январе 2015 года или около того (просто личное предположение, absolutley не обещает, так как я даже не работаю в Google).

лучший способ отладки обещал слушать unhandledRejection событие process.

например, вот как вы можете настроить его и сбросить трассировку стека...

 process.on('unhandledRejection', (reason, p) => {
   console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
   // Stack Trace
   console.log(reason.stack);
 });

вы можете добавить в консоль.журнал() заявление .затем () функция объекта Promise: Вы также можете добавить в .поймать (), если это необходимо.

genericDbCaller(dbName, collectionName, dbFunctionName, params) {
        return new Promise((resolve, reject) => {
            DatabaseContext.instance.getDbConn(dbName)
                .then((dbConn) => {
                    dbConn.get(collectionName)[dbFunctionName].apply(null, params)
                        .then(

                            (docs) =>{
                    ----->>>        console.log(docs);  
                            resolve(docs);
                        })
                        .catch((e)=>{