JavaScriptでの非同期処理において、複数のPromiseを扱う際に便利なメソッドの1つが`Promise.race()`です。このメソッドを使用することで、複数の処理を競争させ、最初に完了した処理の結果を取得することができます。
Promise.race()とは
`Promise.race()`は、複数のPromiseを引数として受け取り、そのうち最も早く完了(resolve または reject)したPromiseの結果を返すメソッドです。その名の通り、Promiseたちの「競争」を行うイメージです。
基本的な使い方
const promise1 = new Promise(resolve => setTimeout(() => resolve('1番'), 500));
const promise2 = new Promise(resolve => setTimeout(() => resolve('2番'), 100));
const promise3 = new Promise(resolve => setTimeout(() => resolve('3番'), 300));
Promise.race([promise1, promise2, promise3])
.then(result => console.log(result)) // '2番'が出力される
.catch(error => console.error(error));この例では、3つのPromiseがそれぞれ異なる時間で完了するように設定されています。`promise2`が最も早く完了(100ミリ秒)するため、その結果が出力されます。
実践的な使用例
タイムアウト処理の実装
function fetchWithTimeout(url, timeout = 5000) {
const fetchPromise = fetch(url);
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('タイムアウトしました')), timeout);
});
return Promise.race([fetchPromise, timeoutPromise]);
}
// 使用例
fetchWithTimeout('https://api.example.com/data', 3000)
.then(response => response.json())
.catch(error => console.error('エラー:', error));複数のAPIからの早い応答を取得
const api1 = fetch('https://api1.example.com/data');
const api2 = fetch('https://api2.example.com/data');
Promise.race([api1, api2])
.then(response => response.json())
.then(data => console.log('最速のAPIからのデータ:', data))
.catch(error => console.error('エラー:', error));注意点
1. エラー処理: いずれかのPromiseが`reject`された場合、その時点で`race()`は終了し、エラーが返されます。
const promise1 = new Promise((_, reject) => setTimeout(() => reject('エラー1'), 100));
const promise2 = new Promise(resolve => setTimeout(() => resolve('成功'), 200));
Promise.race([promise1, promise2])
.then(result => console.log(result))
.catch(error => console.error(error)); // 'エラー1'が出力される2. 空の配列: 引数に空の配列を渡した場合、返されるPromiseは永遠に保留状態となります。
Promise.race([])
.then(result => console.log(result)) // 永遠に実行されない
.catch(error => console.error(error));まとめ
`Promise.race()`は以下のような場面で特に有用です:
- タイムアウト処理の実装
- 複数のAPIから最速のレスポンスを取得
- 非同期処理の競争的な実行が必要な場合
適切なエラーハンドリングと共に使用することで、効率的な非同期処理の制御が可能になります。