如何用 async/await 实现 Promise.race()

How to implement Promise.race() with async/await

如何使用 async 和 await 实现 Promise.race() 方法?

async function promiseRace(promises) {
  const results = [];
  for (const p of promises) {
    await p;
    results.push(p);
  }
  return results[0];
}

我试过像上面那样实现它,但这不起作用。

你不能。使用 await 时,您会停止执行 一个特定的 承诺。要手动实施 Promise.race,您必须 fiddle 回调:

function race(promises) {
  return new Promise((resolve, reject) => {
     for(const promise of promises)
        promise.then(resolve, reject);
  });
}

你不能。就像你不能使用 async/await 实现 Promise 构造函数一样。请记住,await 只是 then 调用的语法糖 - 您不能仅使用它来实现基本的 promise 组合器。

function promiseRace(promises) {
  return new Promise((resolve, reject) => {
    promises.forEach(async (promise) => {
      try {
        const result = await promise;
        resolve(result);
      } catch (err) {
        reject(err);
      }
    });
  });

这是我的解决方案:

   async function promiseRace(promises) {
  const results = [];
  for (const p of promises) {
    results.push(await p);
  }
  return results[0];
}

您可以将包装器承诺与异步等待一起使用。在包装承诺中,保护 resolve/reject 以便只有第一个承诺获胜。

Promise.race 使用 async/await 的示例:

// Implements promise.race
const race = async (promises) => {
  // Create a promise that resolves as soon as
  // any of the promises passed in resolve or reject.
  const raceResultPromise = new Promise((resolve, reject) => {
    // Keep track of whether we've heard back from any promise yet.
    let resolved = false;

    // Protect the resolve call so that only the first
    // promise can resolve the race.
    const resolver = (promisedVal) => {
      if (resolved) {
        return;
      }
      resolved = true;

      resolve(promisedVal);
    };

    // Protect the rejects too because they can end the race.
    const rejector = (promisedErr) => {
      if (resolved) {
        return;
      }
      resolved = true;

      reject(promisedErr);
    };

    // Place the promises in the race, each can
    // call the resolver, but the resolver only
    // allows the first to win.
    promises.forEach(async (promise) => {
      try {
        const promisedVal = await promise;
        resolver(promisedVal);
      } catch (e) {
        rejector(e);
      }
    });
  });

  return raceResultPromise;
};

// *************
// Test Methods
// *************
const fetch = async (millis) => {
  await waitMillis(millis);
  return 'Async result: ' + millis + ' millis.';
};

const waitMillis = (millis) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, millis);
  });
};

const run = async () => {
  let result;

  result = await race([fetch(1), fetch(2), fetch(3)]);
  console.log('Winner', result);

  result = await race([fetch(3), fetch(2), fetch(1)]);
  console.log('Winner', result);

  result = await race([fetch(10), fetch(3), fetch(4)]);
  console.log('Winner', result);
};

run();