「fail-fast」動作なしで複数のpromiseを並列に待機するにはどうすればよいですか? [重複] 質問する

「fail-fast」動作なしで複数のpromiseを並列に待機するにはどうすればよいですか? [重複] 質問する

async/を使用してawait複数のapi呼び出しを並行して実行しています。

async function foo(arr) {
  const results = await Promise.all(arr.map(v => {
     return doAsyncThing(v)
  }))
  return results
}

私は、とは異なりloopsPromise.all 並列実行(つまり、結果を待つ部分は並列です)。

しかし私も知っています:

要素の 1 つが拒否され、Promise.all がすぐに失敗すると、Promise.all は拒否されます。タイムアウト後に解決される 4 つのプロミスがあり、そのうち 1 つがすぐに拒否された場合、Promise.all はすぐに拒否されます。

これを読んでいると、Promise.all5 つの Promise があり、最初に終了した Promise が を返すreject()場合、他の 4 つは事実上キャンセルされ、それらの Promise のresolve()値は失われます。

3 番目の方法はありますか? 実行は事実上並列ですが、1 つの障害によってすべてが台無しにならない方法はありますか?

ベストアンサー1

承認された回答のテクニックは問題を解決できますが、それはアンチパターンです。エラーのある Promise を解決するのは良い方法ではなく、これを行うにはよりクリーンな方法があります。

疑似コードで実行したいことは次のとおりです。

fn task() {
  result-1 = doAsync();
  result-n = doAsync();

  // handle results together
  return handleResults(result-1, ..., result-n)
}

asyncこれは、awaitを使用する必要なしに簡単に実現できますPromise.all。実際の例:

console.clear();

function wait(ms, data) {
  return new Promise( resolve => setTimeout(resolve.bind(this, data), ms) );
}

/** 
 * These will be run in series, because we call
 * a function and immediately wait for each result, 
 * so this will finish in 1s.
 */
async function series() {
  return {
    result1: await wait(500, 'seriesTask1'),
    result2: await wait(500, 'seriesTask2'),
  }
}

/** 
 * While here we call the functions first,
 * then wait for the result later, so 
 * this will finish in 500ms.
 */
async function parallel() {
  const task1 = wait(500, 'parallelTask1');
  const task2 = wait(500, 'parallelTask2');

  return {
    result1: await task1,
    result2: await task2,
  }
}

async function taskRunner(fn, label) {
  const startTime = performance.now();
  console.log(`Task ${label} starting...`);
  let result = await fn();
  console.log(`Task ${label} finished in ${ Number.parseInt(performance.now() - startTime) } miliseconds with,`, result);
}

void taskRunner(series, 'series');
void taskRunner(parallel, 'parallel');

注:このスニペットを実行するには、有効になっているasyncブラウザが必要です。await

この方法では、単にtry/ を使用しcatchてエラーを処理し、parallel関数内で部分的な結果を返すことができます。

おすすめ記事