---
type: how-to
language: javascript
slug: async/parallel
title: "複数の非同期処理を同時に走らせる"
title_tag: "JavaScript 非同期を並列実行する — Promise.all の使い方"
summary: >
  await をループの中で書くと1つずつ順番に待ってしまいます。Promise.all で同時に走らせる
  書き方、1つ失敗したときの扱い、forEach で待てない理由、同時数を絞る方法を確かめます。
description: >
  for の中の await は1つずつ待ちます。map と Promise.all で同時に走らせる書き方、1つ失敗したときの扱い、forEach で待てない理由、同時数の抑え方まで示します。
status: published
difficulty: 3
minutes: 9

versions:
  verified: "Node 22.22.3"
  since: "ES2015"
  deprecated: null
  removed: null

sources:
  - title: "Promise.all — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-promise.all"
  - title: "Promise.allSettled — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-promise.allsettled"
  - title: "Promise — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise"

terms: [Promise, 並列, 直列, 拒否]

links:
  related:
    - javascript/reference/array/map
    - javascript/errors/is-not-a-function
    - javascript/reference/promise/promise
    - javascript/how-to/array/chunk
    - javascript/how-to/async/retry

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

## 答え

`map()` で[key:先に全部始めてから]、`Promise.all()` でまとめて待ちます。

```js run
const load = async (id) => id * 2;

console.log(await Promise.all([1, 2, 3].map(load)));
```
```output
[ 2, 4, 6 ]
```

**結果は渡した順に並びます。** 終わった順ではありません。

## 何が違うのか

`for` の中で `await` すると、[bad:1つ終わってから次を始めます]。

```js run
const load = async (id) => {
  console.log('開始', id);
  return id * 2;
};

for (const id of [1, 2, 3]) {
  console.log('結果', await load(id));
}
```
```output
開始 1
結果 2
開始 2
結果 4
開始 3
結果 6
```

**「開始」と「結果」が交互に出ています。** 前のが終わるまで次が始まっていません。

`map()` で先に全部始めると、こうなります。

```js run
const load = async (id) => {
  console.log('開始', id);
  return id * 2;
};

const running = [1, 2, 3].map(load);

console.log('結果', await Promise.all(running));
```
```output
開始 1
開始 2
開始 3
結果 [ 2, 4, 6 ]
```

**「開始」が3つ続けて出ました。** 3つとも走り出してから、まとめて待っています。

通信のように待ち時間が長い処理なら、**かかる時間が全部の合計から[key:いちばん遅い1つ]に縮みます。**

[dim:計算だけの処理は速くなりません。JavaScript は1本の流れで動くので、待ち時間があるものにしか効きません。]

## 1つ失敗すると全部落ちる

`Promise.all()` は、**1つでも失敗した時点で[bad:全体が失敗になります]。**

```js run
const ok = async (id) => id;
const ng = async () => { throw new Error('3 が読めません'); };

try {
  await Promise.all([ok(1), ng(), ok(2)]);
} catch (error) {
  console.log('落ちた:', error.message);
}
```
```output
落ちた: 3 が読めません
```

**成功した分も受け取れません。** 全部そろわないと意味がないとき（画面を描くのに3つとも要る、など）は、これが正しい動きです。

### 失敗しても他を使いたいなら

`Promise.allSettled()` は、**全部の結果を[key:成否つきで]返します。**

```js run
const ok = async (id) => id;
const ng = async () => { throw new Error('失敗'); };

const results = await Promise.allSettled([ok(1), ng()]);

console.log(results);
console.log(results.filter((r) => r.status === 'fulfilled').map((r) => r.value));
console.log(results.filter((r) => r.status === 'rejected').map((r) => r.reason.message));
```
```output
[ { status: 'fulfilled', value: 1 }, { status: 'rejected', reason: Error: 失敗 } ]
[ 1 ]
[ '失敗' ]
```

**例外は投げられません。** `status` を見て自分で分けます。

| 使うもの | 動き |
|---|---|
| `Promise.all()` | 1つ失敗したら全体が失敗。**全部そろわないと困るとき** |
| `Promise.allSettled()` | 全部待って成否を返す。**取れた分だけ使いたいとき** |
| `Promise.any()` | [num:1]つ成功したらそれを返す |
| `Promise.race()` | 成否を問わず[key:最初に決着した]ものを返す |

```js run
const ng = Promise.reject(new Error('だめ'));
const ok = Promise.resolve('よし');

console.log(await Promise.any([ng, ok]));

try {
  console.log(await Promise.race([ng, ok]));
} catch (error) {
  console.log('race は最初の決着:', error.message);
}
```
```output
よし
race は最初の決着: だめ
```

`any()` は失敗を飛ばして[em:成功を待ちます]。
`race()` は[bad:失敗でも最初なら返します]。**取り違えると、失敗が握りつぶされます。**

## よくある間違い

### `forEach` の中で `await` する

```js bad
const load = async (id) => id * 2;
const out = [];

[1, 2, 3].forEach(async (id) => {
  out.push(await load(id));
});

console.log(out);
```
```output
[]
```

**空のままです。**

`forEach()` は[bad:コールバック関数の戻り値を見ません]。
`async` を付けても `Promise` が返るだけで、`forEach()` はそれを捨てて次へ進みます。
**待っているつもりで、待っていません。**

`map()` に変えて `Promise.all()` で待てば直ります。

```js run
const load = async (id) => id * 2;

console.log(await Promise.all([1, 2, 3].map(load)));
```
```output
[ 2, 4, 6 ]
```

[em:`forEach` は非同期処理と組み合わせない]、と覚えてしまうのが安全です。

### 全部いっぺんに投げる

要素が[num:1000]件あれば、`Promise.all()` は[bad:1000本を同時に走らせます]。
相手のサーバーに断られたり、こちらの資源が尽きたりします。

**数を区切ってください。**

```js run
const load = async (n) => n * 10;
const ids = [1, 2, 3, 4, 5];
const size = 2;
const out = [];

for (let i = 0; i < ids.length; i += size) {
  const chunk = ids.slice(i, i + size);

  console.log('この回:', chunk);
  out.push(...await Promise.all(chunk.map(load)));
}

console.log(out);
```
```output
この回: [ 1, 2 ]
この回: [ 3, 4 ]
この回: [ 5 ]
[ 10, 20, 30, 40, 50 ]
```

**塊の中は並列、塊同士は直列**になります。
`size` で同時に走る数を決められます。

[dim:最後の塊は端数（1件）になります。`slice()` は範囲を超えても落ちないので、割り切れなくても書き足す必要はありません。]
→ [文字列を切り出す・整える](/ja/javascript/learn/string/slice/)

## まとめ

- `map()` で先に始めて `Promise.all()` で待つ。**結果は渡した順**
- 待ち時間のある処理にだけ効く。**計算は速くならない**
- `Promise.all()` は[num:1]つ失敗すると全部失敗。成功分も受け取れない
- 取れた分だけ使うなら `Promise.allSettled()`
- **`forEach` の中の `await` は待たない。** `map()` に変える
- 件数が多いときは[key:塊に区切って]同時数を抑える

`forEach()` と `map()` の違いそのもの（戻り値を見るか捨てるか）は、用語のページで詳しく扱っています。
→ [Array.prototype.map()](/ja/javascript/reference/array/map/)
