あなたがまだ学んでいるかどうかに関わらず、JS言語は独自の急速なペースで進化し続けています。あれよあれよという間に、PromiseのツールキットにはPromise.allを補完するようなPromise.allSettledという別のメソッドが追加され、Promise.allで拒絶されるという痛みにぶつかる問題を軽減してくれます。
Promise.allのペインポイントの解決
ほとんどの場合、Promise.allは次のように複数のPromiseを並行して処理する必要がある場合にうまく機能します。
const delay = n => new Promise(resolve => setTimeout(resolve, n));
const promises = [
delay(100).then(() => 1),
delay(200).then(() => 2),
]
Promise.all(promises).then(values=>console.log(values))
// 最終出力:[1, 2]
しかし、プロミスの1つが例外をスローしてRETRIEVEDされると、状況は厄介になります。
const promises = [
delay(100).then(() => 1),
delay(200).then(() => 2),
Promise.reject(3)
]
Promise.all(promises).then(values=>console.log(values))
// 最終出力: Uncaught 3
Promise.all(promises)
.then(values=>console.log(values))
.catch(err=>console.log(err))
// catch文を追加した後の最終出力: 3
catchで例外をキャッチできるにもかかわらず、正常に実行された他のPromiseからのメッセージが、まるで海に落とされたかのように失われていることに気づくでしょう。
オール・オア・ナッシング、それがPromise.all自体の強い論理であり、ペインポイントの源です。それが間違っているとは言えませんが、Promise.allSettledが足場を固める余地は残されています。
このロジックを処理するためにPromise.allSettledを使ったらどうでしょうか?
const promises = [
delay(100).then(() => 1),
delay(200).then(() => 2),
Promise.reject(3)
]
Promise.allSettled(promises).then(values=>console.log(values))
// 最終出力:
// [
// {status: "fulfilled", value: 1},
// {status: "fulfilled", value: 2},
// {status: "rejected", value: 3},
// ]
すべてのプロミスのデータがthen文に含まれ、各プロミスの戻り値には現在のプロミスのステータスを示す追加のステータスフィールドがあり、どのプロミスの情報も失われていないことがわかります。
そのため、Promise.allSettledを使用する場合は、then文に集中するだけで、例外によってプロミスが中断された場合でも、最初からやり直すことなく、成功したプロミスを適切に処理することができます。
Promise.allSettled の現在のマクロサポート
nodejsはPromise.allSettledのサポートを追加しており、主要なブラウザは2019年のリリースでそれぞれこのメソッドをサポートしています。
この方法をサポートしていない環境では、この方法を実装したオープンソースコミュニティのnpmパッケージを直接参照することができます:
あるいは、Promise.allをベースにしたpolyfillを書いて、プロジェクトにパッチを当てることもできます:
if (Promise && !Promise.allSettled) {
Promise.allSettled = function (promises) {
return Promise.all(promises.map(function (promise) {
return promise.then(function (value) {
return { state: 'fulfilled', value: value };
}).catch(function (reason) {
return { state: 'rejected', reason: reason };
});
}));
};
}
結論
Promise.allSettledはPromise.allを補完するもので,複数のプロミスが並列に存在する場合,rejectが出現すると他のプロミスのデータが失われるという問題に対処するための追加手段を提供します.




