巧みに`Promise.all`実装関数:resolveによって関数全体がresolveされるPromiseがあります.


分散型サービスインタフェースを呼び出すと、インタフェース側はユーザが呼び出すために複数のIPを提供し、1つの戻りが成功すれば成功するという問題がよく発生します.
このような問題に対して、比較的簡単なスキームは、前のインタフェースが正常に戻っていない場合に2番目のインタフェースを呼び出す各インタフェースを順次呼び出すことである.このような利点は、サーバリソースの消費量が小さいが、ユーザーにとって効率が非常に低いことです.1番目のインタフェースを呼び出すのに20秒のタイムアウトエラーが発生してから2番目のインタフェースを呼び出すことを想定し、2番目のインタフェースが20秒のタイムアウトであれば、ユーザは40秒待機している.ユーザの待ち時間は線形に増加し,このような結果は受け入れられない.
良い解決策は、すべてのインタフェースを同時に呼び出すことであり、Promise.raceを思い浮かべる学生もいるかもしれません.でも注意してください:Promise.raceは、1つのPromiseがresolveされるまで待つのではなく、1つのPromiseがfulfillされると、このPromiseがresolveであってもrejectであっても返されます.
私はこのような問題に遭遇したことがあります.もちろんPromise.raceにも一度穴を開けられました.Googleは外国人のこのブログを検索しました:Promise me you won't use Promise.race.ブログでは、この問題を詳細に検討し、Promise.raceで解決策を実現しました.
Promise.properRace = function properRace(promises) {
  if (promises.length < 1) {
    return Promise.reject('Can\'t start a race without promises!');
  }

  // There is no way to know which promise is rejected.
  // So we map it to a new promise to return the index when it fails
  const indexPromises = promises.map((p, index) => p.catch(e => {
    console.debug('Promise rejected in `properRace`: ' + e);
    return Promise.reject(index);
  }));

  return Promise.race(indexPromises).catch(index => {
    // The promise has rejected, remove it from the list of promises and just continue the race.
    promises.splice(index, 1)[0].catch(() => { /* eat this */ });
    return promises.length ? properRace(promises) : Promise.reject('All promises rejected');
  });
};

少し複雑ですが、確かに巧みな方法で、私は初期からこの方法を使っていました.最近振り返ってみると、properRaceの需要はresolveに返されたPromiseが1つあればresolveされることだ.JavaScriptはこのような関数を提供していませんが、rejectによって返されるPromiseが1つあればrejectされるというもう1つの似たような関数を提供しています.
この関数はよく使われています.Promiseです.all
この層を考えると,properRaceを実現するのは簡単である:伝達されたPromise配列の状態を正逆にすればよい.結果は次のとおりです.
Promise.properRace = function properRace(promises) {
  const resolve = Promise.resolve.bind(Promise);
  const reject = Promise.reject.bind(Promise);
  return Promise.all(promises.map(x => x.then(reject, resolve)))
    .then(reject, resolve);
}

完了

2019年7月更新


この方法はPromiseに標準化されている.any