JavaScriptのPromiseによる非同期を経由すると、エラー発生時に非同期の呼び出し元以前のスタックトレースが出力されないので、デバッグに困ることがあった。
けど調べてみたらbluebird*1のlong stack trace機能を使えばそれも含めて出してくれるっぽいということで、試してみた。
上記を読む限り、nodejsでやる場合は NODE_ENV=development
の環境変数で実行する必要があるらしい。
WebpackのproductionではlongStackTraceをfalseにすることを推奨しているということは、おそらくパフォーマンス的には多少影響するということだろう。
というわけで、以下のようなコードを実行する
var Promise = require('bluebird'); const defer = () => new Promise((resolve) => setTimeout(() => resolve(), 0)) const example1 = () => defer() .then(() => { throw new Error('failed'); }); example1() .catch((e) => { console.error(e); });
bluebird使用、long stack trace=OFFの場合
$ node sample.js Error: failed at defer.then (/Users/shun/repos/bluebird-sample/sample.js:10:13) at tryCatcher (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/util.js:16:23) at Promise._settlePromiseFromHandler (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/promise.js:517:31) at Promise._settlePromise (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/promise.js:574:18) at Promise._settlePromise0 (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/promise.js:619:10) at Promise._settlePromises (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/promise.js:699:18) at _drainQueueStep (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/async.js:138:12) at _drainQueue (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/async.js:131:9) at Async._drainQueues (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/async.js:147:5) at Immediate.Async.drainQueues (/Users/shun/repos/bluebird-sample/node_modules/bluebird/js/release/async.js:17:14) at runCallback (timers.js:810:20) at tryOnImmediate (timers.js:768:5) at processImmediate [as _immediateCallback] (timers.js:745:5)
bluebird使用、long stack trace=ONの場合
$ NODE_ENV=development node sample.js Error: failed at defer.then (/Users/shun/repos/bluebird-sample/sample.js:10:13) at runCallback (timers.js:810:20) at tryOnImmediate (timers.js:768:5) at processImmediate [as _immediateCallback] (timers.js:745:5) From previous event: at example1 (/Users/shun/repos/bluebird-sample/sample.js:9:6) at Object.<anonymous> (/Users/shun/repos/bluebird-sample/sample.js:13:1) at Module._compile (module.js:653:30) at Object.Module._extensions..js (module.js:664:10) at Module.load (module.js:566:32) at tryModuleLoad (module.js:506:12) at Function.Module._load (module.js:498:3) at Function.Module.runMain (module.js:694:10) at startup (bootstrap_node.js:204:16) at bootstrap_node.js:625:3
bluebirdを使わない、デフォルトのPromiseの場合
# requireをコメントアウトして実行 $ node sample.js Error: failed at defer.then (/Users/shun/repos/bluebird-sample/sample.js:8:13) at <anonymous>
long stack traceを使うと From previous event というフレーズで非同期呼び出し元以前を辿れるのがわかる。