Promise.all を一言でいうと
Promise.all は、
「複数の Promise を“同時に走らせて”、全部そろったら結果をまとめて受け取るための関数」
です。
たとえば、
ユーザー情報を取得する
投稿一覧を取得する
通知一覧を取得する
この 3 つを「順番に」ではなく「同時に」投げて、
「全部終わったタイミングでまとめて処理したい」 ときに使います。
ここが重要です。Promise.all は「全部終わるのを待つ道具」+「結果を配列でまとめて渡してくれる道具」です。
そして同時に、「1つでも失敗したら全体をエラー扱いにする」 という性質も持っています。
基本の形と動き方
シグネチャ(どう呼ぶか)
基本の形はこうです。
Promise.all([promise1, promise2, promise3])
.then((results) => {
// 全部の Promise が「成功」したときに呼ばれる
})
.catch((error) => {
// 1つでも「失敗」したらここ
});
JavaScriptポイントは 2 つです。
1つ目に、
Promise の配列を渡す こと。
(中身は Promise であれば OK。fetch の返り値など。)
2つ目に、
全部が成功した場合、then に results という 配列 で結果が渡ってくること。
順番は「配列の順番」と一致します。
いちばんシンプルな例
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then((results) => {
console.log(results); // [1, 2, 3]
});
JavaScriptここで起きていることは:
p1, p2, p3 はすでに成功済みの Promise
→ Promise.all は「全部成功している」と判断
→ then の results に [1, 2, 3] が渡る
「配列の 0 番目に p1 の結果、1 番目に p2 の結果、2 番目に p3 の結果」という対応になっています。
実用的な例:複数の API を同時に呼ぶ
ユーザー・投稿・通知をまとめて取得する
それぞれ Promise を返す関数があるとします。
function fetchUser() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("ユーザー取得完了");
resolve({ id: 1, name: "Taro" });
}, 1000);
});
}
function fetchPosts() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("投稿取得完了");
resolve(["投稿1", "投稿2"]);
}, 1500);
});
}
function fetchNotifications() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("通知取得完了");
resolve(["通知A", "通知B"]);
}, 500);
});
}
JavaScriptこれを Promise.all で一気に呼びます。
Promise.all([fetchUser(), fetchPosts(), fetchNotifications()])
.then(([user, posts, notifications]) => {
console.log("ユーザー:", user);
console.log("投稿:", posts);
console.log("通知:", notifications);
})
.catch((err) => {
console.error("どれかの取得に失敗:", err);
});
JavaScript動きとしてはこうです。
fetchUser() 開始(1秒)fetchPosts() 開始(1.5秒)fetchNotifications() 開始(0.5秒)
3つとも「同時に走り始める」。
1番速いもの・遅いものが混ざっていても、
一番遅いものが終わったタイミングで then が呼ばれ、全部の結果が配列で渡される。
ここが重要です。Promise.all は「順番にやる」のではなく、「同時に走らせて、最後にそろえる」ための仕組み
だとイメージしてください。
1つでも失敗したらどうなるか(エラーの性質)
「オールオアナッシング」(全成功か、どこかで失敗か)
Promise.all のエラー処理は、とてもシンプルです。
渡した Promise のうち 1つでも rejected になると、Promise.all 全体が rejected になる。
例を見てみます。
const ok1 = Promise.resolve("OK1");
const fail = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("失敗した Promise"));
}, 1000);
});
const ok2 = new Promise((resolve) => {
setTimeout(() => {
resolve("OK2");
}, 1500);
});
Promise.all([ok1, fail, ok2])
.then((results) => {
console.log("成功:", results);
})
.catch((err) => {
console.error("catch:", err.message);
});
JavaScriptこの場合の流れは:
ok1 → 即成功
fail → 1秒後に失敗
ok2 → 1.5秒後に成功
ですが、Promise.all は、
fail が失敗した瞬間、「全体として rejected」と決定
→ すぐに catch が呼ばれる
→ ok2 の結果は待たない / 使われない
という動きをします。
出力は:
catch: 失敗した Promise
のみです。
ここが重要です。Promise.all は「1つでもダメなら全体としてダメ」という性質。
「全部揃った結果」が欲しいときに使う道具なので、部分的な成功は扱いません。
「どれが失敗したか」の情報
catch に渡されるのは、「最初に失敗した Promise のエラー」です。
上の例では fail が最初に失敗したので、その Error が err になります。
「どの Promise が落ちたか」も知りたければ、
それぞれの reject に少し情報を乗せるのもよくあるやり方です。
const p1 = Promise.reject(new Error("p1 が失敗"));
const p2 = Promise.resolve("OK");
Promise.all([p1, p2]).catch((err) => {
console.error(err.message); // "p1 が失敗"
});
JavaScript結果の配列の順番について
「完了順」ではなく「配列の順番」
ここは初心者が混乱しがちなポイントなので、はっきりさせておきます。
Promise.all に渡した配列が [p1, p2, p3] なら、then の results も常に [p1 の結果, p2 の結果, p3 の結果]
この順番になります。
「どの Promise が先に終わったか」は関係ありません。
例:
const slow = new Promise((resolve) => {
setTimeout(() => resolve("slow"), 1000);
});
const fast = new Promise((resolve) => {
setTimeout(() => resolve("fast"), 100);
});
Promise.all([slow, fast]).then((results) => {
console.log(results); // ["slow", "fast"]
});
JavaScriptfast のほうが 900ms も早く終わりますが、results[0] は slow の結果results[1] は fast の結果
です。
ここが重要です。Promise.all の結果の配列は「完了順」ではなく、「渡したときのインデックス順」。
このおかげで「どの値が何に対応しているか」が分かりやすくなっています。
よくある使い方パターン
配列分割代入で名前をつけて受け取る
配列のままだと results[0] などが分かりづらいので、
分割代入で受け取るのがおすすめです。
Promise.all([fetchUser(), fetchPosts(), fetchNotifications()])
.then(([user, posts, notifications]) => {
console.log(user);
console.log(posts);
console.log(notifications);
});
JavaScript[user, posts, notifications] という形にすれば、
「どれがどの結果か」が一目で分かります。
「普通の値」と Promise が混ざっていてもよい
Promise.all に渡す配列の中身は、
Promise でなくても OK です。
普通の値は「即座に成功した Promise」として扱われます。
Promise.all([
Promise.resolve(1),
2, // これも OK(そのまま 2 になる)
new Promise((resolve) => setTimeout(() => resolve(3), 500)),
]).then((results) => {
console.log(results); // [1, 2, 3]
});
JavaScript使い始めのうちは、「全部 Promise にしておく」方が分かりやすいですが、
こういう柔軟性もある、くらいで覚えておくと良いです。
初心者としての「Promise.all」の押さえどころ
最後に、本当に大事なポイントだけを整理します。
Promise.all([p1, p2, p3]) は、「p1, p2, p3 を同時に走らせて、“全部成功したら” まとめて結果を配列で返す」ための関数。
全部成功したとき → then に [p1 の結果, p2 の結果, p3 の結果] が渡る(順番は配列の順番)。
1つでも失敗したとき → その時点で全体が rejected になり、catch に「最初に失敗した Promise のエラー」が渡る。
「全部揃ってから使いたいデータ」(ユーザー+投稿+通知など)を取るときにとても有効。
結果の配列は完了順ではなく、渡したインデックス順。
混乱しないように、then(([a,b,c]) => ...) のように分割代入で名前をつけて受け取ると読みやすい。
ここが重要です。
Promise.all は「順番に遅くする」のではなく、「同時に投げて待ち時間を短くし、結果だけ最後にそろえる」ための武器です。
練習としては、
setTimeout を使って
- 500ms 後に “A”
- 1000ms 後に “B”
- 200ms 後に “C”
を resolve する Promise を 3 つ作り、Promise.all で [a, b, c] として受け取ってログを出してみてください。
そのとき、
「C が一番早く終わったのに、配列の順番は [A, B, C] なんだ」
という感覚を自分の目で確かめると、Promise.all の挙動がかなりしっかりと腹に落ちるはずです。

