12、aync和await的本质是什么,怎么优化性能 📅 2026/7/6 8:17:11 目录1. async/await 本质是什么2. async/await 不等于多线程3. 性能优化的核心减少无意义的串行 await4. 有依赖关系才串行 await5. 避免循环里逐个 await6. 控制并发而不是无限并发7. 错误处理要根据业务选择8. 不要 await 非必要值9. await 会产生调度成本10. 前端里的优化重点11. Node.js 里的优化重点12. 总结一句话async/await的本质它不是让代码“自动变快”而是把异步任务写成同步风格并在等待 I/O 时释放当前执行权。1. async/await 本质是什么以 JavaScript 为例async function getData() { const result await fetch(/api/data) return result }本质上等价于function getData() { return fetch(/api/data).then(result { return result }) }核心点async function一定返回Promiseawait后面通常是一个Promiseawait会“暂停当前 async 函数”暂停期间不会阻塞整个线程Promise 完成后后续代码进入微任务队列继续执行所以console.log(1) async function test() { console.log(2) await Promise.resolve() console.log(3) } test() console.log(4)输出是1 2 4 3因为await后面的代码会被拆到后续微任务里执行。2. async/await 不等于多线程很多人误解为await task()会让task()在另一个线程跑。不是。如果task()是 CPU 密集型任务比如大循环async function heavy() { for (let i 0; i 1e10; i) {} }即使加了async它仍然会阻塞主线程。async/await主要优化的是网络请求文件读写数据库查询定时器其他 I/O 等待不适合直接优化大量计算图片处理加密压缩大 JSON 解析复杂排序这些需要 Web Worker、Worker Threads、多进程、缓存、算法优化等。3. 性能优化的核心减少无意义的串行 await最常见性能问题是把本来可以并行的任务写成串行。低效写法const user await getUser() const orders await getOrders() const messages await getMessages()如果三个请求互不依赖这样会一个等一个。优化const [user, orders, messages] await Promise.all([ getUser(), getOrders(), getMessages() ])区别串行耗时 ≈ A B C 并行耗时 ≈ max(A, B, C)这是 async/await 性能优化里最重要的一条。4. 有依赖关系才串行 await如果后一个任务依赖前一个结果就必须串行const user await getUser() const orders await getOrders(user.id)这种没法简单并行。但可以把无依赖的部分提前启动const userPromise getUser() const configPromise getConfig() const user await userPromise const ordersPromise getOrders(user.id) const [config, orders] await Promise.all([ configPromise, ordersPromise ])原则是能提前发起的异步任务尽早发起。5. 避免循环里逐个 await低效for (const id of ids) { const item await fetchItem(id) results.push(item) }这是串行。如果可以并发const results await Promise.all( ids.map(id fetchItem(id)) )但注意如果ids很多比如几千个这样会瞬间发出几千个请求可能压垮服务。这时需要限制并发。6. 控制并发而不是无限并发例如使用p-limitimport pLimit from p-limit const limit pLimit(10) const results await Promise.all( ids.map(id limit(() fetchItem(id))) )意思是最多同时跑 10 个。适合批量请求接口批量读文件批量处理任务数据库批量查询性能优化不是“并发越多越好”而是找到合适并发数。7. 错误处理要根据业务选择Promise.all的特点是一个失败整体失败。await Promise.all([ task1(), task2(), task3() ])如果你希望全部执行完再看哪些成功失败用const results await Promise.allSettled([ task1(), task2(), task3() ])结果[ { status: fulfilled, value: ... }, { status: rejected, reason: ... } ]适合批量任务、非强依赖任务。8. 不要 await 非必要值这个写法没必要return await getUser()多数情况下可以写成return getUser()不过在try/catch里需要捕获错误时return await是有意义的async function loadUser() { try { return await getUser() } catch (err) { console.error(err) throw err } }9. await 会产生调度成本await本身也有成本因为它会切分执行流程进入 Promise 微任务调度。通常这个成本很小但在高频代码里要注意。不推荐for (let i 0; i 100000; i) { await Promise.resolve(i) }这会制造大量微任务。如果只是同步计算不要强行 async 化。10. 前端里的优化重点前端使用async/await时主要关注请求并发首屏加载避免阻塞主线程请求取消缓存防抖节流避免重复请求例如请求取消const controller new AbortController() fetch(/api/search?qabc, { signal: controller.signal }) controller.abort()搜索框场景常见优化let controller async function search(keyword) { if (controller) controller.abort() controller new AbortController() const res await fetch(/api/search?q${keyword}, { signal: controller.signal }) return res.json() }避免旧请求慢返回覆盖新结果。11. Node.js 里的优化重点Node.js 中async/await很适合 I/Oconst user await db.user.findUnique(...) const orders await db.order.findMany(...)但常见问题是 N1 查询const users await getUsers() for (const user of users) { user.orders await getOrders(user.id) }优化const users await getUsers() const userIds users.map(u u.id) const orders await getOrdersByUserIds(userIds)数据库场景通常优先考虑批量查询合理索引减少 round-trip连接池配置缓存避免 N1控制并发12. 总结一句话async/await的本质是Promise 的语法糖 状态机 微任务调度。性能优化的关键不是“多写 async”而是独立任务并行Promise.all大批任务限流p-limit有依赖才串行提前启动异步任务CPU 密集任务不要靠 async/await避免循环里无意义串行 await前端注意取消、缓存、防重复请求后端注意批量查询、连接池、N1 问题