Promiseall

Promise.all() : 複数のPromiseを効率的に扱う

Promise.all() は、複数のPromiseを扱う際に非常に便利なメソッドです。複数の非同期処理を並列実行し、すべてが完了した時点での結果をまとめて取得できます。JavaScriptで非同期処理を効率化し、可読性を高めるために、Promise.all()の活用方法を理解しましょう。

Promise.all() の基本:並列実行と結果の集約

Promise.all() は、Promiseの配列を引数に取り、それらのPromiseすべてが履行(resolve)された場合に、それぞれの戻り値を配列に格納した新しいPromiseを返します。もし、いずれかのPromiseが拒否(reject)された場合、Promise.all() 自体も即座に拒否されます。

以下のコードは、Promise.all() を使って複数のPromiseを並列に実行し、すべてのPromiseの結果をまとめて取得する例です:

javascript
const promise1 = Promise.resolve(1);
const promise2 = new Promise((resolve) => setTimeout(() => resolve(2), 1000));
const promise3 = Promise.resolve(3);

Promise.all([promise1, promise2, promise3])
  .then(values => {
    console.log(values); // [1, 2, 3]
  })
  .catch(error => {
    console.error(error); // ここでエラーがキャッチされる
  });​

この例では、promise1promise2promise3 の3つのPromiseを並列に実行しています。すべてのPromiseが解決されると、その結果が配列として then() に渡されます。

Promise.all() を使うメリット:効率的な非同期処理

並列処理

複数の非同期処理を同時に実行できるため、個々の処理が完了するまでの時間を大幅に短縮できます。特に、複数のAPIリクエストを同時に送る場合などに有効です。

簡潔なコード

複数のPromiseを個別に扱う必要がなく、コードがシンプルになります。従来、非同期処理を逐次的に記述する場合は、then() を使って順番に処理を書かなければなりませんが、Promise.all() を使うことでコードの重複を減らすことができます。

エラーハンドリング

Promise.all() では、いずれかのPromiseが拒否された場合、即座にcatchでエラーをキャッチできます。個別にエラーハンドリングを書く必要がないため、エラー処理がシンプルに行えます。

Promise.all() の注意点:フェイルファスト

Promise.all() には「フェイルファスト」の性質があります。これは、いずれかのPromiseが拒否された場合、他のPromiseが解決するのを待たずにすぐにエラーが発生するというものです。

例えば、次のコードでは、promise2が拒否されると、promise1promise3の結果を待たずにエラーが発生します。

javascript
const promise1 = Promise.resolve(1);
const promise2 = Promise.reject('エラー発生');
const promise3 = Promise.resolve(3);

Promise.all([promise1, promise2, promise3])
  .then(values => {
    console.log(values);
  })
  .catch(error => {
    console.error(error); // 'エラー発生' が表示される
  });​

ここでは、promise2 が拒否されると、他のPromiseの結果を待たずに catch が実行され、エラーが処理されます。

Promise.all() と Promise.allSettled() の違い

Promise.allSettled() は、Promise.all() と同様に複数のPromiseを処理しますが、すべてのPromiseが完了(resolveまたはreject)するまで待ちます。それぞれの結果は、状態(fulfilledまたはrejected)と値(または理由)を含むオブジェクトとして返されます。

例えば、以下のように Promise.allSettled() を使うと、すべてのPromiseが完了した結果を得ることができます:

javascript
const promise1 = Promise.resolve(1);
const promise2 = Promise.reject('エラー発生');
const promise3 = Promise.resolve(3);

Promise.allSettled([promise1, promise2, promise3])
  .then(results => {
    console.log(results);
    /*
    [
      { status: 'fulfilled', value: 1 },
      { status: 'rejected', reason: 'エラー発生' },
      { status: 'fulfilled', value: 3 }
    ]
    */
  });​

Promise.allSettled() は、いずれかのPromiseが拒否された場合でも、他のPromiseが解決された結果も含めてすべての結果を返します。これにより、すべての非同期処理の完了を待って結果を処理できるという特徴があります。

Promise.all() の使用例:APIリクエストの並列実行

Promise.all() は、複数のAPIリクエストを並列に実行する場合に特に便利です。以下のコードでは、複数のAPIエンドポイントに対して並列にリクエストを送り、それぞれのレスポンスを取得しています。

javascript
const urls = [
  '/api/data1',
  '/api/data2',
  '/api/data3'
];

const promises = urls.map(url => fetch(url).then(response => response.json()));

Promise.all(promises)
  .then(data => {
    console.log(data); // 各APIのレスポンスデータの配列
  })
  .catch(error => {
    console.error(error); // いずれかのリクエストでエラーが発生した場合
  });​

このコードでは、urls 配列にある各URLに対して fetch リクエストを送信し、その結果を並列に処理しています。Promise.all() はすべてのリクエストが完了するのを待ってから、then のコールバックで結果を受け取ります。

まとめ

Promise.all() は、複数のPromiseを効率的に扱うための強力なツールです。並列処理、簡潔なコード、そしてエラーハンドリングの容易さといったメリットを活用し、JavaScriptの非同期処理を最適化しましょう。Promise.allSettled() との違いを理解し、適切なメソッドを選択することで、より柔軟な非同期処理を実装できます。Promise.all() を上手に使うことで、複雑な非同期処理も簡潔に管理できます。

さらに詳細を知りたい方は、以下のリンクを参考にしてください。

関連記事

タイトル リンク
JavaScriptでのPromiseの使い方 https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Using_promises
Promise.allについての詳細 https://javascript.info/promise-all
JavaScriptのPromiseの理解 https://www.sitepoint.com/understanding-javascript-promises/

FAQ

Q1: Promise.allはどういう時に使うべきですか?
A1: 複数の非同期操作を同時に実行し、全てが完了した後で結果を処理したい時に使用します。
Q2: Promise.allはすべてのPromiseが成功しない限り解決されませんか?
A2: はい、一つでも拒否された場合、Promise.allは即座に拒否されます。
Q3: Promise.allを使うべきでないケースはありますか?
A3: 個々のPromiseの成功や失敗を気にせず、すぐに結果を処理したい場合などには、Promise.allを使うべきではありません。

その他の参考記事:promise 使い方