async 封装是将异步流程纳入统一生命周期管理的标准方式,返回可监听的 promise、支持错误传播、执行时机可预测;其函数必返回 promise,无论内部是否有 await 或异步操作,调用方必须用 await 或 .then() 处理。

async 封装不是让异步变同步的魔法开关,而是把异步流程纳入统一生命周期管理的标准化方式——返回可监听的 Promise、错误可传播、执行时机可预测。
明确 async 函数必返回 Promise
加了 async 的函数,无论内部有没有 await、有没有异步操作,返回值都会被自动包装成 Promise:
- return 123 等价于 Promise.resolve(123)
- throw new Error('fail') 等价于 Promise.reject(new Error('fail'))
- 空函数 async () => {} 调用后也是 pending 状态的 Promise
这点决定了调用方必须用 await 或 .then() 处理结果,不能当作普通同步函数使用。
用 await 切分执行流,而非“暂停线程”
await 的本质是语法糖:它把后续代码包装进微任务,在 Promise settle(resolve/reject)后排队执行。关键点在于:
- 遇到 await 时,JS 引擎立刻执行右侧表达式(如 fetch()),拿到 Promise 后就交出控制权
- 后续逻辑不会立即执行,而是等该 Promise 完成后,作为微任务推入队列
- 多个 await 是串行注册微任务,顺序取决于各 Promise settle 的实际时间
所以写 await a(); await b();,意味着 b 的执行一定在 a 的 Promise resolve 之后,但不等于 a 执行完才开始 b —— b 的发起可能早已开始(比如 a 内部已触发网络请求)。
按需并行,避免无意义串行等待
如果多个异步操作彼此独立(比如查用户、查订单、查配置),强行用 await 逐个等待会拉长总耗时。应改用 Promise.all 并发发起:
- ❌ 串行低效:const u = await getUser(); const o = await getOrder(); const c = await getConfig();
- ✅ 并行优化:const [u, o, c] = await Promise.all([getUser(), getOrder(), getConfig()]);
注意:Promise.all 中任一失败会导致整体 reject;若需容错,可用 Promise.allSettled 或单独 try/catch 包裹每个调用。
深层嵌套时保持 await 链路清晰
当封装函数层层调用(如 getRandom → beWaterFall → db.query),每一层都需满足:
- 函数声明为 async
- 调用下游异步函数时加 await
- 确保所有异步路径最终都 return Promise(哪怕只是 return Promise.resolve())
这样上层才能通过单个 await 控制整个链路完成时机,也便于统一错误捕获和状态追踪。










