JavaScriptの非同期処理において、Promiseは非常に便利な概念です。
しかし複数の非同期タスクを同時に処理する必要がある場合、どのように取り組めばよいのでしょうか?
そこで登場するのが「Promise.all」です。
スクールや学習教材では意外とPromise.allについては深く説明されていないことが多いです。
本記事ではPromise.allの基本的な使い方から、Promiseとの違いについて詳しく解説していきます。
また通常のPromiseとPromise.allの違いについても説明しますので、初学者の方なら非同期処理の理解を深めることができるでしょう。
また動画でも解説しているので必要に応じて活用してください。
Promise.allとは何をしているのか?
Promiseとは非同期処理で使用するものなのでAPIからデータを取得するようなものを作ってみたいと思います。
使用するAPIはjsonplaceholderになります、無料で簡単に使えるAPIです。
https://jsonplaceholder.typicode.com/
const fetchData = async (count) => {
const array = [];
for (let i = 1; i <= count; i++) {
const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${i}`);
const data = await res.json();
await array.push(data);
}
console.log(array);
};
fetchData(5);
こちらのコードは引数に数字を入れた数だけデータを取得して定数arrayに順番に格納していくものです。
単純にデータを取得するだけではなく、取得したデータを別の配列に入れるという手間があります。
定数arrayはコンソールに出力するようにしていて上手くいくと以下のようになります。

定数arrayは最初は空の配列ですが、fetchDataを実行するときに5を引数に入れたので5個のデータを取得して格納できています。
例えばですが引数に100のような大きい数字を入れてみましょう。

もちろん同じように配列に格納してコンソールで出力することができます。
しかし先ほどと違ってコンソールに出力されるまでの時間が全然違います。
実行環境によりますが私のパソコンだと100は1分近くかかりました。
動作自体は問題ないですが、いざサービスの機能として使うには微妙かと思います。
そういった場合にPromise.allを使った書き方に変えると解決できたりします。
同じ動作を以下のように書き変えます。
const fetchData = async (count) => {
const array = [];
// ここから先を変更
for (let i = 1; i <= count; i++) {
array.push(
fetch(`https://jsonplaceholder.typicode.com/todos/${i}`).then((res) =>
res.json()
)
);
}
const data = await Promise.all(array);
console.log(data);
};
fetchData(100);
大きく変わったように見えますが、Promise.allの引数に定数arrayを指定するのを追加しただけで他の部分は書き方を変えているだけです。

同じような結果を得ることができていますし、引数に100を入れても1分近く待つことが無くなりました。
もともとデータを1件取得→取得したデータを定数arrayに格納という作業を繰り返すわけですが、100件といった大きい数を実行すると時間が掛かるわけです。
専門的なことを言うと2つのPromiseを実行することを100回繰り返すと待機時間が増えるからです。
Promise.allはそのような複数のPromiseを並列(ほぼ同時に)で実行してくれます。
そのためプログラムの内容にもよりますが同じ動作でもPromise.allで実行した方が早く完了することがあります。
初学者の方がスクールや学習教材で非同期処理を学ぶ際には1つのPromiseを処理するものしか学びませんので、 Promise.allは言葉だけ紹介されて使い方を知らない方が多いです。
実務ではたまに複数のPromiseを処理しないといけない場面があるので解決策の一つとして覚えておきましょう。
またPromiseについて理解し直したい方は以下の動画をご覧ください。