Promise.all
まずは復習、Promise.all
。
引数にPromiseの配列を渡し、そのPromiseの実行がすべて正常に完了するもしくは1つでも失敗するとresolve/rejectされます。
返り値(then
の引数)には各Promiseの返り値が指定順に渡され、エラー理由(catch
の引数)は一番最初にrejectされたPromiseのものが渡されます。
// p1, p2, p3, ...はPromiseオブジェクト
await Promise.all([p1, p2, p3, ...])
// [p1の返り値, p2の返り値, p3の返り値, ...]
Promise.allSettled
続いて、Promise.allSettled
。
親戚というくらいなので引数は同じ。
そのPromiseの実行がすべて終了する = すべてのPromiseの成功/失敗が決まるとresolve/rejectされます。
Promise.all
との違いは、たとえ1つPromiseがrejectされても処理が続くことです。
返り値には各Promiseの状態と返り値("fulfilled"
か"rejected"
)もしくは理由が指定順に渡されます。
Promise.allSettled
自身は基本的にすべてresolve
されるので、中身がreject
されたこともthen
内で判定します。エラーにはなりません。
await Promise.allSettled([p1, p2, p3, ...])
/*
[{
status: p1の状態,
value: p1の返り値,
}, {
status: p2の状態,
value: p2の返り値
}, {
status: p3の状態,
reason: p3が失敗した理由
},
...
]
*/
Promise.any
ES2021で追加された新キャラです。
引数のPromiseの実行が1つでも正常に完了するもしくはすべて失敗するとresolve/rejectされます。
1つのPromiseがresolveされると、あとのPromiseの結果はすべて無視されます。
返り値には一番最初にresolveされたPromiseの返り値が渡され、エラー理由は「どのPromiseもresolveされなかったよ!」といった趣旨の別のエラーになります。
Promise.all
と逆の性質を持っているとも言えますね。
複数のAPIエンドポイントにリクエストし、一番最初にレスポンスしたものを使いたい、そんなときに便利な新メソッドです。
await Promise.any([p1, p2, p3, ...])
// 一番最初に終わったPromiseの返り値
Promise.race
引数のPromiseの実行が1つでも正常に完了するもしくは1つでも失敗するとresolve/rejectされます。
1つのPromiseの結果が決まると、あとのPromiseの結果はすべて無視されます。
返り値には一番最初にresolveされたPromiseの返り値が渡され、エラー理由も同様に一番最初にrejectされたPromsieのものが渡されます。
await Promise.race([p1, p2, p3, ...])
// 一番最初に終わったPromiseの返り値
まとめ
Promise. | all | allSettled | any | race |
---|---|---|---|---|
1つでも成功 | 処理を続ける | 処理を続ける | その値でresolve | その値でresolve |
1つでも失敗 | その理由でreject | 処理を続ける | 処理を続ける | その理由でreject |
すべて成功 | すべての値でresolve | すべての値でresolve | - | - |
すべて失敗 | - | すべての値でreject | 別のエラーでreject | - |
すべて確定[1] | - | すべての値と理由でresolve | - | - |
Promise. | all | allSettled | any | race |
---|---|---|---|---|
結果が単数 | ✕ | ✕ | ◯ | ◯ |
結果が複数 | ◯ | ◯ | ✕ | ✕ |
理由が単数 | ◯ | ✕ | ◯ | ◯ |
理由が複数 | ✕ | ◯ | ✕ | ✕ |
場面によって適切なメソッドが変わってきます。が、これを制したあなたはPromiseの覇者と言えるでしょう!
-
数を問わず、resolve/rejectがすべて決まったことを示しています。
Promise.allSettled
特有の処理ですね。 ↩︎