实现 Promise.race

手写 Promise.race 方法

问题

从零实现 Promise.race 方法,返回第一个完成(fulfilled 或 rejected)的 Promise 结果。

解答

Promise.myRace = function(promises) {
  return new Promise((resolve, reject) => {
    // 将参数转为数组(支持可迭代对象)
    const arr = Array.from(promises);
    
    // 空数组时,返回的 Promise 永远 pending
    if (arr.length === 0) return;
    
    // 遍历所有 Promise
    for (const p of arr) {
      // 用 Promise.resolve 包装,处理非 Promise 值
      Promise.resolve(p).then(resolve, reject);
    }
  });
};

测试用例

// 测试1:正常竞速
const p1 = new Promise(resolve => setTimeout(() => resolve('p1'), 100));
const p2 = new Promise(resolve => setTimeout(() => resolve('p2'), 50));
const p3 = new Promise(resolve => setTimeout(() => resolve('p3'), 200));

Promise.myRace([p1, p2, p3]).then(console.log); // 'p2'

// 测试2:包含非 Promise 值
Promise.myRace([p1, 'immediate', p3]).then(console.log); // 'immediate'

// 测试3:第一个 reject
const p4 = new Promise((_, reject) => setTimeout(() => reject('error'), 30));

Promise.myRace([p1, p4, p3])
  .then(console.log)
  .catch(console.error); // 'error'

关键点

  • 返回新 Promise,第一个 settled 的结果决定最终状态
  • Promise.resolve() 包装每个元素,兼容非 Promise 值
  • 多次调用 resolve/reject 只有第一次生效,无需额外判断
  • 空数组返回永远 pending 的 Promise(与原生行为一致)
  • 不需要索引,谁先完成谁说了算