如何并行调用多个 async 函数
并行执行多个 async 函数用 Promise.all([fn1(), fn2()]),所有任务同时启动、等待全部完成,结果按传入顺序返回。允许部分失败用 Promise.allSettled,只要第一个结果用 Promise.race/any。
用 Promise.all:把多个 async 函数的调用(注意是调用,返回 Promise 的数组)放进去,它们就会同时启动,await 等到全部完成后拿到结果数组。 关键点是先调用、再统一等待——如果写成逐个 await,就变成串行了。
基本用法
async function main() {
// 错误:串行,总耗时 1s + 1.5s
// const r1 = await fetchUser();
// const r2 = await fetchOrders();
// 正确:并行,总耗时 ≈ 1.5s(最慢的那个)
const [user, orders] = await Promise.all([fetchUser(), fetchOrders()]);
}
注意:fetchUser() 和 fetchOrders() 在传入 Promise.all 的那一刻就已经开始执行了,Promise.all 只是负责"收集结果"。
四种 Promise 组合器
| 方法 | 行为 |
|---|---|
Promise.all |
全部成功才成功;一个失败立即整体 reject |
Promise.allSettled |
等全部结束,成败都收,结果带 status 字段 |
Promise.race |
谁先有结果(无论成败)就返回谁 |
Promise.any |
第一个成功的结果;全失败才 reject |
// 部分失败也能拿到其余结果
const results = await Promise.allSettled(tasks);
const ok = results.filter(r => r.status === 'fulfilled').map(r => r.value);
对数组元素并行
const results = await Promise.all(ids.map(id => fetchById(id)));
常见问题(FAQ)
Q:并行会超限打挂下游接口吗?
会。数组很长时 map + Promise.all 瞬间发出全部请求。用 p-limit 限制并发数,或分批 Promise.all。
Q:Promise.all 中一个失败,其他 Promise 会取消吗?
不会取消(Promise 本身不可取消),它们仍在后台跑完,只是 Promise.all 提前 reject。需要真正取消要配合 AbortController。
Q:async 函数不 await 就调用会怎样?
立即开始执行并返回 Promise。这既是并行的基础,也是"忘记 await 导致错误吞掉"的常见 bug 来源——要么 await,要么显式 .catch()。