はじめに
インターンの中でPromise.allというものに出会ったので勉強がてら少しまとめます。
Promise.allとは?
Promise.allは複数の非同期処理を直列ではなく並列で処理できるメソッドです。
引数にはプロミスの配列などの反復可能な値が入ります。もし全てのプロミスが正常に処理された場合は結果の配列、1つでも正常に処理されなかった場合は即座にエラーが返ります。また処理は並列ですが返り値は引数で渡した順番と同じ順番で配列に格納されます。
例えば以下のような複数のプロミスがあるとします。
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
これらのプロミスをPromise.allの引数に渡して実行すると以下のような結果になります。
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// 結果: [3, 42, "foo"]
Promise.allは1つでもプロミスの処理が失敗すると即座にエラーが出て処理が止まりますが、もし1つのプロミスが失敗したとしても引数で受け取った全てのプロミスの処理を行いたい場合はPromiss.allSettledというのを使うみたいです。どちらを使うかは何を実現したいかで変わってきそうです。
Promise.allを使うと良さそうな場面
実行順序が重要ではなく、各処理が互いに独立している場合はPromise.allを使うと良さそうです。
例えば以下のように引数で受け取った値を1秒後に解決する関数があるとします。
function func(task) {
return new Promise((resolve) =>
setTimeout(() => {
resolve(task);
}, 1000)
);
}
Promise.allを使う場合と使わない場合で以下のように書けます。
const tasks = [1, 2, 3]
// Promise.allで並列処理する場合
async function usePromiseAll() {
await Promise.all(tasks.map(func));
}
// for ofで直列処理する場合
async function useForOf() {
for (const task of tasks) {
await func(task);
}
}
単純計算でPromise.allを使う場合はtasksの値が全て並列で処理されるので1秒、forで行なっている方は1つ1つ実行するので3秒かかることになります。
おわりに
あまり直列や並列という考えが今までなかったので勉強になりました。
参考