Promise 与 async/await

把 Promise 状态机与 async/await 语法糖放到同一模型,强调错误传播、并行与取消边界。

#type / synthesis #status / growing #tech / dev #resource / javascript #resource / ecmascript

[!info] 关联笔记

Promise 与 async/await

这个概念为什么出现

回调地狱让错误处理与并行组合失控。Promise 提供统一的一次性完成态;async/await 让异步流程用同步外形书写,但仍运行在事件循环上。

[!abstract] 一句话理解 async 函数返回 Promise;await 等待 Promise 兑现并把后续注册为微任务续体。

最小可运行示例

场景:拉取 SKU 详情再拉库存

function fetchSku(id) {
  return Promise.resolve({ id, name: '缠绕膜' })
}
function fetchStock(id) {
  return Promise.resolve({ id, qty: 3 })
}

async function loadSkuCard(id) {
  // 业务意图:详情页需要名称与库存
  // 教学点:await 失败会抛到 async 函数的 rejection
  try {
    const sku = await fetchSku(id)
    const stock = await fetchStock(id) // 串行
    return { ...sku, ...stock }
  } catch (err) {
    throw new Error('loadSkuCard failed: ' + err.message)
  }
}

async function loadSkuCardFaster(id) {
  // 教学点:独立请求用 Promise.all 并行
  const [sku, stock] = await Promise.all([fetchSku(id), fetchStock(id)])
  return { ...sku, ...stock }
}

loadSkuCard('A-01').then(console.log)
loadSkuCardFaster('A-01').then(console.log)

核心模型

概念要点
状态pending → fulfilled/rejected,一锤定音
then返回新 Promise,可链式转换
async永远返回 Promise
await解包 Promise,错误变 throw
all/race/allSettled/any组合并发

边界

  • await 在非 async 中非法(模块顶层 await 是特例)
  • 忘记 await 会变成“火后忘记”
  • 取消需要 AbortController 等,Promise 自身不自带取消语义

常见误区

[!warning] 常见误区:async 函数里同步 throw 与 reject 完全无关 同步 throw 会被包装成该 async 返回 Promise 的 rejection。

工程实践

  • 并行能 all 就别无故串行 await
  • 统一错误类型边界
  • 与 UI 框架结合时注意竞态(过期响应)

本节总结

async/await 是可读性工具,Promise 才是契约;组合与错误传播决定系统稳健度。

自测题

  1. async function f(){ return 1 } 的返回值类型?
  2. 两个独立 I/O 为何避免顺序 await?
参考答案
  1. Promise,兑现为 1。
  2. 顺序 await 拉长总等待;Promise.all 可重叠等待。
创建于 2025/1/1 更新于 2026/7/15