JavaScript Promise の並列処理:all・allSettled・race の使い方
複数の非同期処理を並列で実行するには Promise.all・Promise.allSettled・Promise.race・Promise.any を使います。
早わかりまとめ
| メソッド | 解決タイミング | 失敗時の挙動 |
|---|---|---|
Promise.all |
全件成功したとき | 1件でも失敗したら即 reject |
Promise.allSettled |
全件完了したとき | 失敗してもすべての結果を収集 |
Promise.race |
最初の1件が完了したとき | 失敗でも成功でも最初の結果を返す |
Promise.any |
最初の成功が出たとき | 全件失敗したとき reject |
Promise.all:全件成功が前提のとき
const fetchUser = () => fetch('/api/user').then((r) => r.json())
const fetchPosts = () => fetch('/api/posts').then((r) => r.json())
const [user, posts] = await Promise.all([fetchUser(), fetchPosts()])
console.log(user, posts)
1件でも失敗(reject)すると全体が reject になります。「全部成功しないと意味がない」ケースに使います。
try {
const results = await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments(),
])
} catch (e) {
// どれか1件が失敗したら catch に来る
console.error(e)
}
Promise.allSettled:失敗してもすべての結果を収集したいとき
const results = await Promise.allSettled([
fetch('/api/user').then((r) => r.json()),
fetch('/api/broken-endpoint').then((r) => r.json()),
fetch('/api/posts').then((r) => r.json()),
])
results.forEach((result) => {
if (result.status === 'fulfilled') {
console.log('成功:', result.value)
} else {
console.error('失敗:', result.reason)
}
})
各要素が { status: 'fulfilled', value } または { status: 'rejected', reason } の形になります。失敗があっても処理を止めずに全件収集したいときに使います。
Promise.race:最初に完了したものを使うとき
const timeout = (ms) =>
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), ms))
try {
const result = await Promise.race([
fetch('/api/data').then((r) => r.json()),
timeout(3000),
])
console.log(result)
} catch (e) {
console.error('タイムアウトまたはエラー:', e.message)
}
タイムアウト処理の実装でよく使います。成功・失敗どちらでも、最初に完了した Promise の結果を返します。
Promise.any:最初の成功を使うとき
// 複数のミラーからどれか1つ取れれば良いケース
const result = await Promise.any([
fetch('https://mirror1.example.com/data'),
fetch('https://mirror2.example.com/data'),
fetch('https://mirror3.example.com/data'),
])
Promise.race との違い:Promise.any は失敗を無視して最初の成功を待ちます。全件失敗したときだけ AggregateError で reject されます。
直列処理との比較
// ❌ 直列(合計時間 = A + B + C) const a = await fetchA() const b = await fetchB() const c = await fetchC() // ✅ 並列(合計時間 ≈ max(A, B, C)) const [a, b, c] = await Promise.all([fetchA(), fetchB(), fetchC()])
互いに依存しない処理は Promise.all で並列化するとパフォーマンスが向上します。
まとめ
| したいこと | 使うもの |
|---|---|
| 全件成功したら結果を使う | Promise.all |
| 失敗があっても全件の結果を収集する | Promise.allSettled |
| 最初に完了した結果を使う(タイムアウトなど) | Promise.race |
| 最初に成功した結果を使う | Promise.any |
| 順番に依存する処理を直列で実行する | await を直列に書く |