多个 await 默认串行执行,但关键在于 promise 创建时机;提前创建会导致实际并行而 await 仅等待已 settled 结果,应封装异步操作为函数并在 await 时调用,独立任务用 promise.all 实现并行,依赖任务分层处理,错误处理需匹配执行模型。

多个 await 默认是串行执行的,但“串行”不等于“必须一个接一个发起”,关键在于 Promise 是何时创建的。真正耗时的,往往不是等待本身,而是提前启动了本可以延后或并行的任务。
await 等的是 Promise 状态,不是“发起时机”
常见误区:写 await a(); await b(); 就以为 b() 一定在 a() 完成后才开始。其实如果 a() 和 b() 返回的 Promise 已被提前创建(比如在函数开头就 new 了),它们的异步操作早已并行运行——await b() 只是立刻拿到已 settled 的结果,看似“快”,实则浪费了等待时间,还可能引发逻辑错乱。
- ✅ 正确做法:把异步操作封装成函数,只在
await时调用,确保“发起”和“等待”同步发生 - ❌ 错误写法:
const p1 = apiCall1(); const p2 = apiCall2(); await p1; await p2;—— 两个请求同时发出,第二个 await 毫无意义地等一个已完成的 Promise - ✅ 推荐写法:
await apiCall1(); await apiCall2();—— 第二个请求真正在第一个完成后才发起
需要并行?别用连续 await,改用 Promise.all
当多个异步任务彼此独立、无依赖,且你希望总耗时接近最慢那个任务时,连续 await 是性能陷阱。它会让请求一个接一个发,总时间是所有耗时之和。
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
- 串行(慢):
const a = await fetch('/a'); const b = await fetch('/b'); const c = await fetch('/c'); - 并行(快):
const [a, b, c] = await Promise.all([fetch('/a'), fetch('/b'), fetch('/c')]); - 想容错?用
Promise.allSettled,它总会返回全部结果,每个元素带status字段,可区分成功或失败
依赖关系决定结构:先串行获取 ID,再并行拉取数据
真实场景常是混合模式:前一步结果是后几步的输入,但后续几步之间又互不依赖。这时应分层处理,避免把所有 await 堆在一起。
- 先串行拿基础数据:
const user = await fetch('/api/user').then(r => r.json()); - 再基于 user 并行发起关联请求:
const [posts, prefs, stats] = await Promise.all([ fetch(`/api/posts?uid=${user.id}`), fetch(`/api/prefs?uid=${user.id}`), fetch(`/api/stats?uid=${user.id}`) ]) - 这样既保证了依赖正确,又榨干了并发潜力
错误处理要匹配执行模型
串行和并行的错误传播机制不同,catch 方式也得跟着变。
- 串行 await:任一 reject,后续 await 不执行,一个 try/catch 就能捕获全部
- Promise.all:只要一个 reject,整个 all 就 reject,需在外部 catch;若想单个失败不影响整体,改用
allSettled+ 后续过滤 - 混用时注意:串行部分出错,后面并行逻辑根本不会执行,所以关键前置步骤务必加兜底或重试










