Bluebirdの finally
のドキュメントはありますが、then
との違いはまだよくわかりません。
明確にするために、then
の後にcatch
が呼び出される理由を正確に知っています。 Iwantキャッチ後に呼び出されます。それが意図です。私の質問は次のとおりです:Iwantコードがpromiseの状態に関係なく常に実行される場合、then
とfinally
そのために?
私はこのテストを作成しました:
_var Promise = require("bluebird");
function test1 () {
console.log("RESOLVE + THEN + CATCH + THEN");
return new Promise((resolve, reject) => resolve())
.then(() => console.log("then"))
.catch(err => console.log("error:", err.message))
.then(() => console.log("end"));
}
function test2 () {
console.log("REJECT + THEN + CATCH + THEN");
return new Promise((resolve, reject) => reject(new Error("rejected")))
.then(() => console.log("then"))
.catch(err => console.log("error:", err.message))
.then(() => console.log("end"));
}
function test3 () {
console.log("RESOLVE + THEN + CATCH + FINALLY");
return new Promise((resolve, reject) => resolve())
.then(() => console.log("then"))
.catch(err => console.log("error:", err.message))
.finally(() => console.log("end"));
}
function test4 () {
console.log("REJECT + THEN + CATCH + FINALLY");
return new Promise((resolve, reject) => reject(new Error("rejected")))
.then(() => console.log("then"))
.catch(err => console.log("error:", err.message))
.finally(() => console.log("end"));
}
// run tests "sequentially" so console output doesn't get blended
setTimeout(test1, 500);
setTimeout(test2, 1000);
setTimeout(test3, 1500);
setTimeout(test4, 2000);
_
これは4つのケースをテストします。
.then(...).catch(...).then(...)
約束の解決済み。.then(...).catch(...).then(...)
は、約束を拒否しました。.then(...).catch(...).finally(...)
約束の解決済み。.then(...).catch(...).finally(...)
は、約束を拒否しました。私が見る結果は、1 + 2が3 + 4と同じように振る舞うケースです:最後のビット(テストに応じてthen
またはfinally
)は、意図したとおりに、それより前に何が起きても実行されます。そのプログラムの出力は次のとおりです。
_RESOLVE + THEN + CATCH + THEN
then
end
REJECT + THEN + CATCH + THEN
error: rejected
end
RESOLVE + THEN + CATCH + FINALLY
then
end
REJECT + THEN + CATCH + FINALLY
error: rejected
end
_
さて、私が尋ねている理由は、 私が尋ねたこの他の質問についてのコメント :
約束がサポートするかどうかはわかりませんが、最後の_
.then
_を_.finally
_に変更して、busy
が常にクリアされるようにする必要があります。
then
についての私の非常に限られた知識と上記のテストから、then
で十分であるように思われます。しかし、そのコメントの後、私は自分自身とthen
を使用して「最終的に」コードを実行することの安全性に疑問を抱いています。
だから私の質問は:then
とfinally
の違いは何ですか? lookは同じように動作しますが、いつfinally
の代わりにthen
を使用する必要がありますか?
最初の違い:エラーが発生した場所でエラーをキャッチしたくない場合がありますが、この関数を使用するコードでは、エラーをキャッチしません。その場合、then()
とfinally()
を置き換えることはできません。
エラーが発生したかどうかに関係なく、何かをクリーンアップする必要がある場合があります(参照の無効化、タイムアウトのクリアなど)。そこでfinally()
を使用します。
2番目の違い:catch()
に渡す関数もスローする可能性があります。その場合、Promiseが拒否され、次のthen()
は呼び出されません。
(したがって、最終的にcatchがエラーで実行される前に、それを知りませんでした)
ええ、それがfinally()
のポイントです。解決された値を変更せずに、どんな状況でも実行されます。
try {} finally {}
、キャッチなし。
.then
と.finally
は同じではありません。
.then
は主要なPromiseプリミティブです。 Promises/A + spec で徹底的に定義されており、すべてのpromiseライブラリがそれを実装します。
Bluebird .finally
ハンドラーは、「約束の運命に関係なく呼び出されます」。したがって、未処理の例外は依然として.finally
をトリガーします。
new Promise((resolve, reject) => reject(false))
.finally(a => console.log('finally', a))
// finally undefined
// Unhandled rejection false
new Promise((resolve, reject) => reject(false))
.then(a => console.log('then', a))
// Unhandled rejection false
.finally
は、promiseの解決された値を変更せず、promiseチェーンの結果を受け取りません。
new Promise((resolve, reject) => reject(false))
.catch(e => {
console.log(e)
return 2
})
.finally(a => {
console.log('finally', a)
return 1
})
.then(res => console.log('res', res))
// finally undefined
// res 2
テストはすべてのエラーをキャッチし、フロー制御にプロミスのみを使用し、プロミスチェーンに沿って解決/拒否される値に依存しないため、メソッドはテストケースで似ています。
大丈夫、いくつかのチャットとKevinBの多くの助けの後、少なくとも1つの違いを見つけました。次の2つの新しいテストを検討してください。
function test5 () {
console.log("REJECT + THEN + CATCH/THROW + THEN");
return new Promise((resolve, reject) => reject(new Error("rejected")))
.then(() => console.log("then"))
.catch(function(err) { throw new Error("error in catch"); })
.then(() => console.log("end"));
}
function test6 () {
console.log("REJECT + THEN + CATCH/THROW + FINALLY");
return new Promise((resolve, reject) => reject(new Error("rejected")))
.then(() => console.log("then"))
.catch(function(err) { throw new Error("error in catch"); })
.finally(() => console.log("end"));
}
これらでは、promiseは拒否されますが、catch
からエラーがスローされます。
両方の場合、最終的にプロミスは拒否されますが、finally
の場合、finally
はまだ実行されますが、then
は実行されません。
それが違い。これらはalmostと同じですが、唯一の例外はcatch
ハンドラからエラーがスローされ、finally
が実行され、then
はしません。
これは、私が引用したコメントにもメリットがあることを意味します。エラーハンドラで別のエラーが発生した場合、then
はクリーンアップを保証しませんが、finally
はクリーンアップを保証します。それは私が行方不明だったケースです。