Skip to content

Latest commit

 

History

History
76 lines (55 loc) · 3.63 KB

onrejected-or-catch.adoc

File metadata and controls

76 lines (55 loc) · 3.63 KB

then or catch?

前の章.catchpromise.then(undefined, onRejected) であるということを紹介しました。

この書籍では基本的には、.catchを使い .then とは分けてエラーハンドリングを書くようにしています。

ここでは、.then でまとめて指定した場合と、どのような違いがでるかについて学んでいきましょう。

エラー処理ができないonRejected

次のようなコードを見ていきます。

then-throw-error.js
link:embed/embed-then-throw-error.js[role=include]
// 実行例
badMain(function(){
    console.log("BAD");
});
goodMain(function(){
    console.log("GOOD");
});

このコード例では、(必ずしも悪いわけではないですが)良くないパターンの badMain と ちゃんとエラーハンドリングが行える goodMain があります。

badMain がなぜ良くないかというと、.then の第二引数にはエラー処理を書くことができますが、 そのエラー処理は第一引数の onFulfilled で指定した関数内で起きたエラーをキャッチすることはできません。

つまり、この場合、 throwError でエラーがおきても、onRejected に指定した関数は呼ばれることなく、 どこでエラーが発生したのかわからなくなってしまいます。

それに対して、 goodMainthrowErroronRejected となるように書かれています。 この場合は throwError でエラーが発生しても、次のchainである .catch が呼ばれるため、エラーハンドリングを行うことができます。

.then のonRejectedが扱う処理は、その(またはそれ以前の)promiseオブジェクトに対してであって、 .then に書かれたonFulfilledは対象ではないためこのような違いが生まれます。

Note

.then.catch はその場で新しいpromiseオブジェクトを作って返します。 Promiseではchainする度に異なるpromiseオブジェクトに対して処理を書くようになっています。

Then Catch flow
Figure 1. Then Catch flow

この場合の thenPromise.resolve(42) に対する処理となり、 onFulfilled で例外が発生しても、同じ then で指定された onRejected はキャッチすることはありません。

この then で発生した例外をキャッチできるのは、次のchainで書かれた catch となります。

もちろん .catch.then のエイリアスなので、下記のように .then を使っても問題はありませんが、 .catch を使ったほうが意図が明確で分かりやすいでしょう。

Promise.resolve(42).then(throwError).then(null, onRejected);

まとめ

ここでは次のようなことについて学びました。

  1. promise.then(onFulfilled, onRejected) において

    • onFulfilled で例外がおきても、この onRejected はキャッチできない

  2. promise.then(onFulfilled).catch(onRejected) とした場合

    • then で発生した例外を .catch でキャッチできる

  3. .then.catchに本質的な意味の違いはない

    • 使い分けると意図が明確になる

badMain のような書き方をすると、意図とは異なりエラーハンドリングができないケースが存在することは覚えておきましょう。