promise.race的测试用例核心是验证其返回第一个settled(fulfilled或rejected)的promise结果:①返回首个fulfilled值;②首个rejected即整体reject;③空数组永远pending;④非promise值被同步包装resolve;⑤区别于promise.all的全量等待逻辑。

Promise.race 的测试用例核心是验证它是否**正确返回第一个 settled(fulfilled 或 rejected)的 Promise 结果**,而不是最快完成的(注意:settled ≠ resolved,reject 也算 settled)。下面给出结构清晰、覆盖关键场景的测试用例写法,基于 Jest(主流且易上手),逻辑通用,其他测试框架可类推。
测试 Promise.race 返回第一个 fulfilled 的 Promise
这是最常见场景:多个 Promise 中,最快 resolve 的那个应被 race 返回。
- 创建两个 Promise:一个 10ms 后 resolve('fast'),另一个 100ms 后 resolve('slow')
- 调用 Promise.race([p1, p2]),并 await 其结果
- 断言结果为 'fast',且不等待 100ms
test('returns the first fulfilled promise', async () => {
const fast = new Promise(res => setTimeout(() => res('fast'), 10));
const slow = new Promise(res => setTimeout(() => res('slow'), 100));
const result = await Promise.race([fast, slow]);
expect(result).toBe('fast');
});
测试 Promise.race 返回第一个 rejected 的 Promise
race 不只看 resolve —— 第一个 reject 也会立即触发 race 的 rejection,这点常被忽略。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 构造一个 5ms 后 reject(new Error('boom')) 的 Promise
- 另一个 50ms 后 resolve('ok')
- 用 expect(...).rejects.toThrow(...) 捕获 race 的拒绝结果
- 确保错误消息匹配(不是静默吞掉错误)
const fail = new Promise((_, rej) => setTimeout(() => rej(new Error('boom')), 5));
const success = new Promise(res => setTimeout(() => res('ok'), 50));
await expect(Promise.race([fail, success])).rejects.toThrow('boom');
});
测试空数组或非 Promise 成员的边界情况
Promise.race([]) 行为特殊:它会**永远 pending(不 resolve 也不 reject)**;而传入含非 Promise 值(如字符串、数字)时,会自动包装为 resolved Promise。
- Promise.race([]) 应永不结束 → 可用 expect(...).toNeverResolve()(Jest 29+)或超时断言
- Promise.race([1, Promise.resolve(2)]) 应立即返回 1 → 因为 1 被转为 Promise.resolve(1),且同步 resolve,快于异步的 Promise.resolve(2)
const race = Promise.race([]);
await expect(race).toNeverResolve(); // Jest 29+
});
test('non-promise values are wrapped and resolved synchronously', async () => {
const result = await Promise.race([42, new Promise(res => setTimeout(() => res(99), 10))]);
expect(result).toBe(42);
});
测试 Promise.race 与 Promise.all 的行为差异(辅助理解)
这不是必须的单元测试,但写一个对比用例能帮你确认 race 是否真按“首个 settled”工作,而非“全部完成”:
- 准备两个 Promise:p1 30ms 后 reject,p2 10ms 后 resolve
- Promise.race([p1,p2]) 应立刻 reject(因 p2 先 settle?错!p2 是 resolve,但 p1 是 reject —— 谁先执行完 .then/.catch 就算谁。实际取决于 setTimeout 时间差)
- 关键是:若 p2 是 5ms resolve,p1 是 10ms reject,则 race 返回 p2 的值;反之则 reject
- 而 Promise.all([p1,p2]) 必须等两者都 settle,且任一 reject 就整体 reject
test('race is not all: settles on first outcome, not all', async () => {
const p1 = new Promise(res => setTimeout(res, 5, 'first')); // resolves at 5ms
const p2 = new Promise((_, rej) => setTimeout(rej, 10, new Error('second'))); // rejects at 10ms
const raceResult = await Promise.race([p1, p2]);
expect(raceResult).toBe('first'); // ✅ race returns first settled (p1)
await expect(Promise.all([p1, p2])).rejects.toThrow('second'); // ✅ all fails on any reject
});
不复杂但容易忽略:重点不是“谁快”,而是“谁先 settled”。写测试时,用 setTimeout 控制时间差要足够明显(比如 5ms vs 50ms),避免竞态干扰;同时别忘了 reject 和非 Promise 值这两类易错场景。










