溝畑です。
今回はES2020で追加された「Promise.allSettled」を紹介。
Promise.allSettled
Promise.allSettled()> Promise.allSettled() メソッドは、与えられたすべてのプロミスが満足したか拒否された後に、それぞれのプロミスの結果を記述した配列オブジェクトで解決されるプロミスを返します。
複数の非同期処理を実行させるものなら「Promise.all」があるじゃないか...。
と思うかもしれませんが、Promise.allの場合、いずれかがエラーだとcatchに入ります。
1 2 3 4 5 6 7 8 9 |
const promises = [api1, api2] Promise.all(promises) .then(res => { // success }) .catch(err => { // どちらかがエラーなら、その時点でここに入る }) |
allSettledは、成功失敗に関わらず、それぞれの結果を返します。
1 2 3 4 5 6 7 8 9 10 |
const promises = [api1, api2] Promise.allSettled(promises) .then(resolve => { console.log(resolve) // [ // { status: 'fulfilled', value: api1のresponse }, // { status: 'rejected', reason: 'Error' } // ] }) |
このようになります。
どういう場面で使えるでしょうか?
使い所
・APIで複数のファイルをアップロードする。・ただし、どのファイルがアップロードに成功、失敗したのか、最後に表示する。
こんなケースを考えます。
ファイルを複数一気にアップロードをかけて、事細かにAPIが各ファイルに対する情報を返してくれればいいのですが、そうではない場合。。。
この場合、1ファイルずつアップロードAPIを叩いて、各Promiseをidか何かで紐付けて状態管理する必要があると思います。
Promise.allだと・・・。
1 2 3 4 5 6 7 8 |
const uploads = [file1upload, file2upload, file3upload] Promise.all(uploads) .then(res => { }) .catch(err => { // どれかがエラーなら、その時点でcatchに入る。 }) |
なぜこんなケースを例にするかというと、以前これに似たケースを「エラーをresolveする」といった形で実装したことがあるためです。
こんな雰囲気です。
1 2 3 4 5 6 7 8 9 10 11 |
function uploadFile(files) { const formData = new FormData() files.forEach(file => { formData.append('files[]', file) }) return axios.post('upload', formData) .then(res => Promise.resolve(res.data)) .catch(err => Promise.resolve(new Error(err)) } |
こうしておけば、どこかがエラーでも、全ての処理が終わった段階で処理を受けることができるわけです。
これがいいやり方かどうかは置いておきましょう。
こんなやり方をせずとも、Promise.allSettledだと
1 2 3 4 5 6 |
const uploads = [file1upload, file2upload, file3upload] Promise.allSettled(uploads) .then(resolve=> { // 全てのupload状態が分かる }) |
やりたかったことがこれ一発でできそうですね。
結構ニッチな事例をあげましたが、それ以外でも使い道は多いはずです。
似たような悩みをお持ちの方、allSettledお試しあれ、、、。
これ以外にも、Promise.raceやES2021で追加予定のPromise.anyなどもあるので、
全てallではなく、用途によって使い分けてみましょう。