await仅控制等待点,不改变promise启动时机;真正决定并发与否的是promise创建时间,而非await位置。

await 本身不改变 Promise 的启动时机,只控制“等待点”——它让 async 函数暂停执行,直到右侧的 Promise 状态变为 fulfilled 或 rejected。真正决定顺序的,是 Promise 何时被创建、何时开始运行,而不是 await 出现在哪一行。
关键:Promise 创建时机决定实际并发行为
常见误区是以为写 await promiseA 就会让 promiseA “这时才开始执行”。但只要 promiseA = new Promise(...) 已提前定义,其中的异步操作(如 setTimeout、fetch)在构造时就已启动。
- 两个提前声明的 Promise,即使后 await,也会并行运行
- 想串行,就得让第二个 Promise 的创建推迟到第一个 await 完成之后
- 典型错误写法:
const p1 = apiCall(); const p2 = apiCall(); await p1; await p2;→ 两个请求同时发 - 正确写法:
await apiCall(); await apiCall();→ 第二个调用在第一个返回后才发起
循环中按序执行:for...of + await 最直接
需要逐个处理列表(比如上传文件、批量请求),且必须严格按索引顺序完成,就用带 await 的同步循环:
- 用
for (const item of list),每次迭代都await当前任务 - 避免把
async () => {...}写在循环里却不调用——那只是定义函数,没触发任何异步操作 - 每个 await 都应包裹在 try/catch 中,单次失败不影响后续项继续执行
- 若某次失败需跳过,捕获后
continue;若需重试,可加简单重试逻辑
区分串行与并行:看业务依赖,不是看语法
是否必须等前一个结果,决定了该用串行还是并行:
- 依赖前序数据(如 token 刷新后才能发下一请求)→ 必须串行:逐个 await
- 数据彼此独立(如加载多个用户头像)→ 应并行:先发起全部请求,再
await Promise.all([...]) - 既要并发又要保序(如上传 5 个文件,按顺序编号返回结果)→ 用
Promise.allSettled+ 映射原始顺序 - 混搭场景(前两步串行,后三步并行)→ 拆成多个 async 块,按需组合
错误处理不能省:await 不会自动吞掉异常
未捕获的 Promise rejection 会让整个 async 函数返回 rejected Promise,可能引发上层静默失败或 unhandledrejection 报错:
- 每个关键 await 前后建议加 try/catch,尤其在循环或链式调用中
- 不要只在外层包一个 try/catch —— 那样一次失败就中断全部流程
- 对 fetch 类操作,注意
response.ok和网络错误是两回事,都要检查 - reject 后可选择 throw 继续冒泡,或返回默认值、记录日志后继续











