
本文介绍一种替代 Promise.all 的方法,使多个异步 Promise 按其真实 resolve 时间先后顺序返回结果,而非按输入数组索引顺序,适用于定时器差异明显、需优先处理快速响应的场景。
本文介绍一种替代 `promise.all` 的方法,使多个异步 promise 按其真实 resolve 时间先后顺序返回结果,而非按输入数组索引顺序,适用于定时器差异明显、需优先处理快速响应的场景。
在标准 JavaScript 中,Promise.all() 保证返回结果数组的索引顺序与输入 Promise 数组完全一致,无论各 Promise 实际完成时间如何。例如:P3(1000ms)、P1(3000ms)、P2(5000ms)按此顺序 resolve,但 Promise.all([P1, P2, P3]) 仍返回 ['R1', 'R2', 'R3'] —— 这并非按“完成时间排序”,而是严格遵循输入位置。
若需真正按首次 resolve 到最后 resolve 的自然时序收集结果(即 ['R3', 'R1', 'R2']),可实现一个自定义函数 allInFulfillmentOrder:
async function allInFulfillmentOrder(promises) {
const result = [];
await Promise.all(
Array.from(promises, (p) => p.then((value) => result.push(value)))
);
return result;
}该函数核心逻辑在于:
- 使用
Array.from(promises, ...)遍历每个 Promise,为每个注册.then()回调; - 每个回调仅执行
result.push(value),利用 JS 引用特性确保所有回调共享同一result数组; -
Promise.all(...)仅用于等待全部 Promise 完成(任一 reject 将导致整体 reject),不依赖其返回值; - 最终直接返回按 fulfill 时间累积的
result数组。
完整示例:
const P1 = new Promise(resolve => setTimeout(() => resolve('R1'), 3000));
const P2 = new Promise(resolve => setTimeout(() => resolve('R2'), 5000));
const P3 = new Promise(resolve => setTimeout(() => resolve('R3'), 1000));
async function fetchInitialData(arr) {
return allInFulfillmentOrder(arr);
}
fetchInitialData([P1, P2, P3])
.then(data => console.log('result', data)); // 输出: ['R3', 'R1', 'R2']⚠️ 注意事项:
- 该方案不保留原始 Promise 的索引信息,仅按完成顺序输出值;
- 若需同时获取值与完成时间戳,可在
.then()中补充Date.now()记录; - 所有 Promise 仍并行执行,本方案仅改变结果收集方式,不影响并发行为;
- 若存在 reject,
allInFulfillmentOrder会立即 reject(行为与Promise.all一致),已 resolve 的值不会丢失,但无法通过.catch()获取部分结果 —— 如需容错,应改用Promise.allSettled并自行排序。
总结:当业务逻辑依赖响应快慢(如 UI 优先渲染轻量数据、降级策略触发、竞态请求取最快结果等),allInFulfillmentOrder 是简洁可靠的解决方案,兼顾语义清晰性与执行效率。

















