同期にせよ非同期にせよ、普通にエラーをthrowしてcatchしないでおくとブラウザの開発者ツールのコンソールにエラーとして表示されます。
setTimeout(function() {throw new Error('async')}, 1000);
throw new Error('sync');
// Uncaught Error: sync
// Uncaught Error: async 1秒後
Promiseのエラーは実際はrejectなので、本質的にはErrorがthrowされた状態ではありません。が、親切なコンソールではエラーハンドルを忘れていた場合(promiseがrejectされるまでに、一回もcatchハンドラーが設定されていなかった場合)に以下のように表示されます。
親切なコンソール(FirefoxやChrome)
Promise.reject(new Error('promise!!!'));
// Uncaught (in promise) Error: promise!!!
これは開発中にうっかりcatchし忘れるのを防ぐのに大変便利ですので、基本的に抑制すべきではありません。
しかし、1パターンだけわかっていて抑制したい場合があります。それは「今このpromiseはrejectするが、catchハンドラーがsetされるのはもっと後」という場合です。
var promise = Promise.reject(new Error('promise!!!'));
setTimeout(function() {promise.catch(/* 適切なエラーハンドル */);}, 1000);
// Uncaught (in promise) Error: promise!!!
// 後々エラーハンドルするんだけど、コンソールにはUncaught Errorが出てしまう!
これは「promiseがrejectされるまでに、一回もcatchハンドラーが設定されていなかった場合」に表示されるのですから、以下のように即座に一回promiseをcatchしてしまえば抑制できます。
var promise = Promise.reject(new Error('promise!!!'));
// これで抑制できる!!(後で見る人にとっては意味不明なのでコメントでこの記事のURLを貼っておこう)
promise.catch(function(e) {});
setTimeout(function() {promise.catch(/* 適切なエラーハンドル */);}, 1000);
// なにもでない
なお、似てるようですが下記の書き方は大変まずいです。
var promise = Promise.reject(new Error('promise!!!')).catch(function(e) {});
setTimeout(function() {promise.catch(/* 適切なエラーハンドル…でcatchできない!!! */);}, 1000);
// なにもでない
これだと変数promise
には「エラーをすべて握りつぶした後のpromise」が登録されてしまいます。後続のエラーハンドルが全く機能しなくなってしまうので、絶対にやめましょう。