web-dev-qa-db-ja.com

javascriptの約束をデバッグする方法は?

私は約束に基づく非同期コードをデバッグする方法を理解しようとしています。 PromisesとはECMAScript 6ベースのPromisesを意味し、デバッグとは組み込みの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 Promiseを適切にデバッグする方法ですか?

68
YemSalat

これは議論するのに最適なトピックです。悲しいニュースは、これは実際にはネイティブの約束では非常に難しいことです。

Chromeで生のES6 Promiseをデバッグするのは恐ろしいことです。これはエラーを静かに抑制し、catchを省略するたびにPromiseが失敗したことを示すものではないためです。 更新:Chromeは未処理の拒否を記録するようになりました (方法についてはこのリンクを参照)

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

Firefoxでは、未処理の拒否の検出を実行するため、状況は少し改善されますが、それでもまだおかしくなり、約束をどこにでも割り当てても機能しません。

それで、何ができますか?

Bluebird -ES6 Promiseのスーパーセットであり、すぐに交換できます。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()
        });
    });
});

ネイティブの約束では-これはサイレント障害であり、デバッグが非常に困難です-Bluebirdの約束では、デフォルトでコンソールに大きな赤いエラーが表示されます:

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)

デバッグが完了したら、それを交換してネイティブの約束に戻ることができます。個人的には、本番環境でエラーが発生していることを知っていることを大切にしていますので、お勧めしませんが、間違いなく実行可能です。

58

*これはあなたの質問に直接答えるわけではありませんが、それでも役に立つかもしれません。

Chrome devtoolsは最近、Promiseなどの非同期コードのデバッグに役立つ新しい機能を取得しました。

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

基本的に、[ソース]タブの[非同期]チェックボックスをオンにすると、Chromeは、同期コードであるかのように呼び出しスタックを再構築します。

Screenshot

13
goat

この答えは、Benjamin Gruenbaumの答えへの追加です。promiseチェーンで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's the error!
at Context.<anonymous> (test/test_promise.js:64:23)
12
Matthias M

彼らはChromeのデバッグツールで動作しているようです。詳細については、このスレッドを参照してください。

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

これがすでに開発バージョンまたはベータバージョンにあるかどうかはチェックしていませんが、まもなくリリースされることを願っています。その後、2015年1月頃に通常版に含まれるかもしれません(個人的な推測であり、Googleでも働いていないので絶対に約束しません)。

1
Johan Bergens

Promiseオブジェクトの.then()関数にconsole.log()ステートメントを追加できます。必要に応じて、.catch()に追加することもできます。

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)=>{
0
cepix

約束されたものをデバッグする最良の方法は、unhandledRejectionprocessイベントをリッスンすることです。

たとえば、これを設定してスタックトレースをダンプする方法を次に示します...

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