【実践編】JavaScriptでPromise.allSettled()を使って、全てのPromiseの結果を取得する方法

2024-06-21

JavaScript ですべての Promise が完了するまで待機する方法(一部拒否されても)

しかし、複数の Promise を実行する場合、すべての Promise が完了するまで待機したいことがあります。また、一部の Promise が拒否されても、残りの Promise の結果を取得したい場合もあります。

以下では、すべての Promise が完了するまで待機する方法と、一部の Promise が拒否されても、残りの Promise の結果を取得する方法について、ES6 Promise を使って詳しく解説します。

Promise.all() を使用する

Promise.all() は、与えられたすべての Promise が完了するのを待って、それらの結果を配列として返す関数です。すべての Promise が正常に完了した場合のみ、Promise.all() は成功した Promise を返します。1つでも Promise が拒否されると、Promise.all() は即座に拒否され、拒否された理由を伝えるエラー情報を含む Promise を返します。

以下は、Promise.all() を使ってすべての Promise が完了するまで待機する例です。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 1 resolved'), 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('Promise 2 rejected')), 2000);
});

const promise3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 3 resolved'), 3000);
});

Promise.all([promise1, promise2, promise3])
  .then(results => {
    console.log(results); // 結果: [ 'Promise 1 resolved', 'Promise 3 resolved' ] (Promise 2 は拒否されたため、results には含まれません)
  })
  .catch(error => {
    console.error(error); // エラー: Error: Promise 2 rejected
  });

この例では、promise2 が拒否されているため、Promise.all() は拒否され、console.error() にエラー情報が出力されます。

Promise.allSettled() を使用する

Promise.allSettled() は、与えられたすべての Promise が完了するのを待って、それらの結果をPromise オブジェクトの配列として返す関数です。Promise.all() と異なり、すべての Promise の完了結果 (成功または失敗) を取得できます

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 1 resolved'), 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('Promise 2 rejected')), 2000);
});

const promise3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 3 resolved'), 3000);
});

Promise.allSettled([promise1, promise2, promise3])
  .then(results => {
    console.log(results);
    // 結果: [ { status: 'fulfilled', value: 'Promise 1 resolved' },
    //        { status: 'rejected', reason: Error: Promise 2 rejected },
    //        { status: 'fulfilled', value: 'Promise 3 resolved' } ]
  });

この例では、promise2 が拒否されていますが、Promise.allSettled()すべての Promise の結果を含む Promise オブジェクトの配列を返します。各 Promise オブジェクトには、status プロパティ ('fulfilled' または 'rejected') と、value または reason プロパティ (Promise の結果またはエラー情報) が含まれます。

async/await を使用する

async/await は、Promise をより同期的に扱うための構文です。async キーワードでマークされた関数は、Promise を返します。await キーワードを使って、非同期処理の結果を待つことができます。

async function main() {
  const promise1 = new Promise((resolve, reject) => {
    setTimeout(() =>



JavaScript ですべての Promise が完了するまで待機するサンプルコード(一部拒否されても)

Promise.all() を使用する

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 1 resolved'), 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('Promise 2 rejected')), 2000);
});

const promise3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 3 resolved'), 3000);
});

Promise.all([promise1, promise2, promise3])
  .then(results => {
    console.log(results); // 結果: [ 'Promise 1 resolved', 'Promise 3 resolved' ] (Promise 2 は拒否されたため、results には含まれません)
  })
  .catch(error => {
    console.error(error); // エラー: Error: Promise 2 rejected
  });

解説:

  • このコードは、3 つの Promise を作成します。
  • Promise.all() が成功した場合、then() ハンドラが呼び出され、Promise の結果が results 配列に格納されます。
  • Promise.all() が失敗した場合、catch() ハンドラが呼び出され、エラー情報がコンソールに出力されます。

Promise.allSettled() を使用する

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 1 resolved'), 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('Promise 2 rejected')), 2000);
});

const promise3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 3 resolved'), 3000);
});

Promise.allSettled([promise1, promise2, promise3])
  .then(results => {
    console.log(results);
    // 結果: [ { status: 'fulfilled', value: 'Promise 1 resolved' },
    //        { status: 'rejected', reason: Error: Promise 2 rejected },
    //        { status: 'fulfilled', value: 'Promise 3 resolved' } ]
  });
  • 各 Promise オブジェクトには、status プロパティ ('fulfilled' または 'rejected') と、value または reason プロパティ (Promise の結果またはエラー情報) が含まれます。

async/await を使用する

async function main() {
  const result1 = await promise1;
  const result2 = await promise2;
  const result3 = await promise3;
  console.log(result1, result2, result3);
}

main().catch(error => {
  console.error(error);
});

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 1 resolved'), 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('Promise 2 rejected')), 2000);
});

const promise3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 3 resolved'), 3000);
});
  • このコードは、async 関数 main() を定義します。
  • await キーワードを使って、promise1promise2promise3 の結果を順番に待ちます。
  • catch() ハンドラを使って、非同期処理中に発生するエラーを処理します。

補足:

  • 上記のコードはあくまで一例です。状況に応じて、適切な方法を選択してください。
  • より複雑な処理の場合は、エラー



JavaScriptで全てのPromiseが完了するまで待機する方法(一部拒否されても) - その他の方法

自作のPromise関数:

以下のコードは、Promise.all() や Promise.allSettled() と同様の機能を持つ自作のPromise関数です。全てのPromiseが完了し、結果またはエラー情報を含む配列を返します。

function myAll(promises) {
  const results = [];
  let errors = [];

  return new Promise((resolve, reject) => {
    let pending = promises.length;

    promises.forEach((promise, i) => {
      promise.then(result => {
        results[i] = result;
        pending--;

        if (pending === 0) {
          resolve(results);
        }
      }).catch(error => {
        errors.push(error);
        pending--;

        if (pending === 0) {
          if (errors.length > 0) {
            reject(errors[0]);
          } else {
            reject(new Error('All promises rejected'));
          }
        }
      });
    });
  });
}

この関数は、以下の例のように使用できます。

myAll([promise1, promise2, promise3])
  .then(results => console.log(results))
  .catch(error => console.error(error));

再帰処理:

以下のコードは、再帰処理を使って全てのPromiseが完了するまで待機する方法です。

function allRecursive(promises, results = [], errors = []) {
  if (promises.length === 0) {
    if (errors.length > 0) {
      return Promise.reject(errors[0]);
    } else {
      return Promise.resolve(results);
    }
  }

  const promise = promises.shift();
  return promise.then(result => {
    results.push(result);
    return allRecursive(promises, results, errors);
  }).catch(error => {
    errors.push(error);
    return allRecursive(promises, results, errors);
  });
}
allRecursive([promise1, promise2, promise3])
  .then(results => console.log(results))
  .catch(error => console.error(error));

外部ライブラリの利用:

Bluebird や Q などの外部ライブラリには、Promise.all()Promise.allSettled() と同様の機能を持つメソッドが用意されています。これらのライブラリを使用することで、より簡単に全てのPromiseを処理することができます。

    注意事項:

    上記の方法はいずれも、非同期処理を扱うため、コードの理解と注意が必要です。また、状況に応じて適切な方法を選択する必要があります。


    javascript promise es6-promise


    インタラクティブに!JavaScript Chart Library で操作できるグラフ・チャート

    主な機能豊富なグラフ種類: 棒グラフ、折れ線グラフ、円グラフ、散布図など、様々な種類のグラフを作成できます。データの読み込み: CSV ファイル、JSON ファイル、JavaScript 配列など、様々なデータソースからデータを読み込むことができます。...


    【超簡単】たった一行で親div内のdivを削除!JavaScript、jQuery、HTMLを使いこなそう

    このチュートリアルでは、JavaScript、jQuery、HTML を使って、親 <div> 内のすべての <div> コンテンツを削除する方法を解説します。それぞれの方法について、コード例と詳細な説明を提供します。方法 1: JavaScript の removeChild メソッドを使用する...


    jQuery Ajax POST Example with PHP

    この解説では、jQuery Ajax POST を使って、データを PHP サーバーに送信し、処理結果をブラウザに表示する方法について、初心者向けに分かりやすく説明します。以下のコードは、ユーザーが入力した名前と年齢を PHP サーバーに送信し、サーバーから返送されたメッセージを表示する例です。...


    JavaScript の getBoundingClientRect() メソッドを使用して DIV の寸法変更を検出する方法

    このページでは、JavaScript、jQuery、および HTML を使用して DIV の寸法変更を検出する方法について解説します。方法DIV の寸法変更を検出するには、以下の 3 つの方法があります。JavaScript の MutationObserver API を使用する...


    Angular、Promise、RxJSにおける「What is the difference between Promises and Observables?」

    Promiseは、非同期処理の完了を待つための仕組みです。処理が完了したら、成功または失敗の結果を返します。特徴:単一の値またはエラーを返す状態は「完了」または「失敗」の2つのみ処理のキャンセルはできないネストが複雑になりやすい例:Observableは、非同期処理のデータストリームを表す仕組みです。時間経過とともに複数の値を発行し、購読者はその値を受け取ることができます。...