bluebird promise FAQ を見て、そこでは .then(success, fail)
はアンチパターンです と言及されています。試行錯誤については、その説明がよくわかりません。次の何が問題なのですか?
some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
この例では、以下を正しい方法として提案しているようです。
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
違いは何ですか?
違いは何ですか?
.then()
呼び出しは、コールバックがエラーをスローした場合に拒否されるプロミスを返します。これは、成功したlogger
が失敗すると、エラーは次の.catch()
コールバックに渡されますが、fail
と並んでいるsuccess
コールバックには渡されません] _。
制御フローダイアグラムは次のとおりです。
同期コードで表現するには:
_// some_promise_call().then(logger.log, logger.log)
then: {
try {
var results = some_call();
} catch(e) {
logger.log(e);
break then;
} // else
logger.log(results);
}
_
2番目のlog
(.then()
の最初の引数に似ています)は、例外が発生しなかった場合にのみ実行されます。ラベル付きブロックとbreak
ステートメントは少し奇妙に感じますが、これは実際には pythonが_try-except-else
_ for (推奨読書!)です。
_// some_promise_call().then(logger.log).catch(logger.log)
try {
var results = some_call();
logger.log(results);
} catch(e) {
logger.log(e);
}
_
catch
ロガーは、成功ロガー呼び出しからの例外も処理します。
違いはたくさんあります。
試行錯誤についての説明はよくわかりません
引数は、通常、処理のすべてのステップでエラーをキャッチすることであり、チェーンで使用しないでください。すべてのエラーを処理する最終ハンドラが1つだけであることが期待されます-一方、「アンチパターン」を使用すると、一部のthen-callbackのエラーは処理されません。
ただし、このパターンは実際には非常に便利です:正確にこのステップで発生したエラーを処理し、何かを実行したい場合完全に異なるエラーが発生しなかった場合、つまりエラーが回復不可能な場合。 注意してくださいこれは分岐あなたの制御フローであること。もちろん、これが望ましい場合もあります。
次の何が問題なのですか?
_some_promise_call() .then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
_
コールバックを繰り返す必要があったこと。あなたはむしろ欲しい
_some_promise_call()
.catch(function(e) {
return e; // it's OK, we'll just log it
})
.done(function(res) {
logger.log(res);
});
_
これには .finally()
を使用することも検討してください。
2つはまったく同一ではありません。違いは、最初の例はsuccess
ハンドラーでスローされた例外をキャッチしないことです。そのため、メソッドが解決済みのプロミスのみを返す場合、よくあることですが、末尾のcatch
ハンドラー(または、空のthen
パラメーターを持つ別のsuccess
)が必要です。確かに、then
ハンドラーは、潜在的に失敗する可能性のあることを何もしていない可能性があります。その場合、2つのパラメーターthen
を1つ使用しても問題ありません。
しかし、リンク先のテキストのポイントは、then
が多くの非同期ステップをチェーンする機能においてコールバックと比較して最も有用であり、実際にこれを行うと、then
の2パラメーター形式は微妙に動作しないことだと思います上記の理由により、予想どおり。ミッドチェーンで使用すると特に直感に反します。
多くの複雑な非同期処理を行って、私が認める以上にこのようなコーナーにぶつかった人として、このアンチパターンを避け、個別のハンドラーアプローチを使用することを本当にお勧めします。
両方の長所と短所を調べることで、状況にどちらが適切かを計算で推測できます。これらは、約束を実装するための2つの主なアプローチです。どちらにもプラスとマイナスがあります
キャッチアプローチ
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
利点
欠点
成功/エラーアプローチ
some_promise_call()
.then(function success(res) { logger.log(res) },
function error(err) { logger.log(err) })
利点
Disavantages
catch
が必要になります.then().catch()
を使用すると、ワークフローを実現するために必要なPromise Chainingを有効にできます。データベースからいくつかの情報を読み取る必要があり、それを非同期APIに渡し、応答を操作する必要がある場合があります。応答をデータベースにプッシュすることができます。これらすべてのワークフローをコンセプトで処理することは実行可能ですが、管理が非常に困難です。より良い解決策はthen().then().then().then().catch()
で、これは一度だけキャッチしてすべてのエラーを受け取り、コードのmaintainabilityを維持できます。
簡単な説明:
ES2018で
引数onRejectedを指定してcatchメソッドが呼び出されると、次の手順が実行されます。
- Promiseをthisの値にします。
- 戻る? Invoke(promise、 "then"、"undefined、onRejected")。
つまり:
promise.then(f1).catch(f2)
等しい
promise.then(f1).then(undefiend, f2)