複数の非同期処理を統合するには?

JavaScriptで複数の非同期処理をまとめて扱う場合、Promise.all、Promise.race、Promise.allSettledなどを使用できます。
これらを使うことで、複数の通信処理をまとめて実行したり、すべての処理が終わるのを待ったり、最初に完了した処理だけを利用したりできます。
非同期処理を適切に統合できると、API通信やファイル読み込みなどを効率よく管理できます。
Promise.allとは?
Promise.all()は、複数の非同期処理がすべて成功するまで待つためのメソッドです。
すべてのPromiseが成功すると、結果が配列として返されます。一方で、どれか1つでも失敗すると、その時点でcatchが実行されます。
Promise.allの使用例
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve("データ1取得完了");
}, 1000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve("データ2取得完了");
}, 2000);
});
const promise3 = new Promise((resolve) => {
setTimeout(() => {
resolve("データ3取得完了");
}, 3000);
});
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results);
})
.catch((error) => {
console.error(error);
});
この例では、3つの非同期処理がすべて完了した後にthenが実行されます。
実行結果は、次のようになります。
[
"データ1取得完了",
"データ2取得完了",
"データ3取得完了"
]
Promise.all()の結果は、完了した順番ではなく、配列に指定した順番で返されます。
Promise.raceとは?
Promise.race()は、複数の非同期処理のうち、最初に完了したPromiseの結果だけを取得するメソッドです。
最初に完了したPromiseが成功すればthenが実行され、失敗すればcatchが実行されます。
Promise.raceの使用例
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve("データ1取得完了");
}, 1000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve("データ2取得完了");
}, 2000);
});
const promise3 = new Promise((resolve) => {
setTimeout(() => {
resolve("データ3取得完了");
}, 3000);
});
Promise.race([promise1, promise2, promise3])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
この例では、最も早く完了するpromise1の結果が取得されます。
データ1取得完了
なお、Promise.race()で最初の結果が返された後も、他のPromiseの処理自体が自動的にキャンセルされるわけではありません。結果として利用されないだけです。
Promise.allとPromise.raceの違い
Promise.all()とPromise.race()の違いをまとめると、次のようになります。
| 特徴 | Promise.all | Promise.race |
|---|---|---|
| 処理の終了タイミング | すべての非同期処理が成功したとき。 | 最初の非同期処理が完了したとき。 |
| 成功・失敗の扱い | 1つでも失敗すると全体が失敗する。 | 最初に完了したPromiseの結果で成功・失敗が決まる。 |
| 結果 | すべての結果が配列で返る。 | 最初に完了したPromiseの結果だけが返る。 |
| 主な用途 | 複数のデータをすべて取得したい場合。 | タイムアウト処理や最速の結果を使いたい場合。 |
Promise.allSettledとは?
Promise.allSettled()は、複数の非同期処理が成功・失敗に関係なくすべて完了するまで待つメソッドです。
Promise.all()は1つでも失敗するとcatchへ移動しますが、Promise.allSettled()はすべての結果を確認できます。
Promise.allSettledの使用例
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve("データ1取得完了");
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("データ2取得失敗");
}, 2000);
});
Promise.allSettled([promise1, promise2])
.then((results) => {
console.log(results);
});
実行結果は、次のような形式になります。
[
{
status: "fulfilled",
value: "データ1取得完了"
},
{
status: "rejected",
reason: "データ2取得失敗"
}
]
fulfilledは成功、rejectedは失敗を表します。
async/awaitと組み合わせる
現在のJavaScriptでは、Promise.all()などをasync/awaitと組み合わせて使うことも多くあります。
Promise.allとasync/awaitの例
async function fetchAllData() {
try {
const results = await Promise.all([
fetch("/api/user").then((response) => response.json()),
fetch("/api/posts").then((response) => response.json())
]);
console.log(results);
} catch (error) {
console.error("データ取得に失敗しました:", error);
}
}
fetchAllData();
この例では、ユーザー情報と投稿情報を並行して取得しています。順番にawaitするよりも、同時に開始できるため効率的です。
Promise.anyとは?
Promise.any()は、複数のPromiseのうち、最初に成功したPromiseの結果を返すメソッドです。
Promise.race()は最初に完了したPromiseが失敗すると全体も失敗しますが、Promise.any()は失敗したPromiseを無視し、最初に成功した結果を待ちます。
Promise.any([
Promise.reject("失敗1"),
Promise.resolve("成功"),
Promise.reject("失敗2")
])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
この例では、最初に成功した"成功"が結果として取得されます。
使い分けの目安
| メソッド | 使う場面 |
|---|---|
Promise.all() |
すべての処理が成功する必要がある場合。 |
Promise.allSettled() |
成功・失敗に関係なく、すべての結果を確認したい場合。 |
Promise.race() |
最初に完了した処理だけを使いたい場合。 |
Promise.any() |
最初に成功した結果だけを使いたい場合。 |
まとめ
- 複数の非同期処理を統合するには、
Promise.all()、Promise.race()、Promise.allSettled()などを使います。 Promise.all()は、すべてのPromiseが成功したときに結果を配列で返します。Promise.race()は、最初に完了したPromiseの結果だけを返します。Promise.allSettled()は、成功・失敗に関係なくすべての結果を取得できます。Promise.any()は、最初に成功したPromiseの結果を返します。async/awaitと組み合わせると、複数の非同期処理を読みやすく管理できます。- 用途に応じてメソッドを使い分けることで、効率的な非同期処理を書けます。