私は約束に基づく非同期コードをデバッグする方法を理解しようとしています。 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を適切にデバッグする方法ですか?
これは議論するのに最適なトピックです。悲しいニュースは、これは実際にはネイティブの約束では非常に難しいことです。
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)
デバッグが完了したら、それを交換してネイティブの約束に戻ることができます。個人的には、本番環境でエラーが発生していることを知っていることを大切にしていますので、お勧めしませんが、間違いなく実行可能です。
*これはあなたの質問に直接答えるわけではありませんが、それでも役に立つかもしれません。
Chrome devtoolsは最近、Promiseなどの非同期コードのデバッグに役立つ新しい機能を取得しました。
http://www.html5rocks.com/en/tutorials/developertools/async-call-stack/
基本的に、[ソース]タブの[非同期]チェックボックスをオンにすると、Chromeは、同期コードであるかのように呼び出しスタックを再構築します。
この答えは、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)
彼らはChromeのデバッグツールで動作しているようです。詳細については、このスレッドを参照してください。
https://code.google.com/p/v8/issues/detail?id=309
これがすでに開発バージョンまたはベータバージョンにあるかどうかはチェックしていませんが、まもなくリリースされることを願っています。その後、2015年1月頃に通常版に含まれるかもしれません(個人的な推測であり、Googleでも働いていないので絶対に約束しません)。
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)=>{
約束されたものをデバッグする最良の方法は、unhandledRejection
のprocess
イベントをリッスンすることです。
たとえば、これを設定してスタックトレースをダンプする方法を次に示します...
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
// Stack Trace
console.log(reason.stack);
});