第4章 异步编程与 Promise/async-await

异步编程是 Node.js 的核心能力,也是高频面试考点。从回调地狱到 Promise 链,再到 async/await,考察重点依次为:理解异步模型 → 掌握链式控制 → 编写可维护的错误处理。
类型判断 事件循环 对比优缺点 代码示例 错误处理 回答框架:先判题型 → 再讲原理 → 对比优劣 → 现场写码 → 最后强调错误处理 try/catch vs .catch 未捕获异常 Promise 内部错误 async 内部错误 全局兜底方案 追问路径:面试官会从“怎么处理错误”一路追问到“全局未捕获怎么办”

面试问答卡片

问题1:什么是回调地狱?如何解决?

考察点:对异步嵌套的认识、代码组织能力、Promise 与 async/await 的基础掌握。

回答框架:定义 → 示例 → 缺点 → 解决方案(Promise 链 / async-await)→ 最佳实践。

示例回答:“回调地狱指多层异步嵌套导致代码向右扩散,难以维护。我通常使用 Promise 链或 async/await 改写:先用 Promise 把每个异步操作包装,再通过 .then 链式调用或 await 顺序等待。同时利用命名函数拆分逻辑,避免匿名函数堆积。”

可能追问:“你觉得 Promise 链解决了什么新问题?” / “如果 Promise 链中某个环节出错,如何恢复?”
避坑提醒:不要只说“用 async/await”,要现场展示如何将一个嵌套的回调重构为链式或 async 函数,并主动提及错误处理。

问题2:Promise 链如何保证顺序执行?如何传递参数?

考察点:Promise 链式调用机制、值传递、错误冒泡。

回答框架:链式调用原理 → then 返回新 Promise → 返回值传递 → 错误处理位置。

示例回答:“每个 .then 返回一个新 Promise,下一个 .then 等待其 resolve。可通过 return 传递值。错误会沿链冒泡到最近的 .catch。我习惯在链尾统一放一个 .catch,避免每个 then 都做错误处理,并利用 finally 做清理工作。”

可能追问:“如果链中某个 then 返回了一个 rejected 状态的 Promise,后续怎么走?” / “如何中断 Promise 链?”
避坑提醒:强调“在 then 中 return 一个 rejected 的 Promise”可以跳到 catch,但不要忘记处理未捕获的 rejection。最好演示一个完整链。

问题3:async/await 有哪些最佳实践?注意哪些坑?

考察点:异步编程熟练度、错误处理、并发控制、微任务理解。

回答框架:声明方式 → try/catch 包裹 → 避免顺序等待 → 结合 Promise.all → 注意 forEach 中的 async。

示例回答:“我遵循三条原则:1) 使用 try/catch 捕获所有 await 错误;2) 需要并发时用 Promise.all,避免不必要的串行;3) 不要在 forEach 中直接使用 async,应改用 for...of 或 Promise.allSettled。此外,用 .finally 清理资源。”

可能追问:“await 在 for 循环中是串行还是并行?” / “如何同时处理多个异步任务且出错后不中断?”
避坑提醒:一定要说明 forEach 中的 await 不会等待,这是经典陷阱。同时展示 Promise.allSettled 用于部分失败场景。

项目案例

项目名称高并发消息推送服务 – PushEngine
业务背景为 SaaS 平台百万用户提供实时 WebSocket 消息推送(订单通知、IM 消息等)。
规模指标QPS 50,000+,同时在线连接 100,000+,日推送量 1.2 亿条。
技术栈Node.js + Express + Redis Pub/Sub + WebSocket (ws) + PM2 + 自定义背压模块
核心难点1) 大量并发连接下的背压控制(防止内存溢出);2) 消息顺序保证(单用户通道有序);3) 单个 WebSocket 断开后的重连与消息补推。
面试高频追问“如何用 Promise 和 async/await 管理 WebSocket 读写?” “推送失败时如何处理未完成的任务?” “多个异步写入如何保证不相互干扰?”
可迁移回答话术“我们使用 async/await + Promise.allSettled 管理并发推送,对每个连接维护一个写队列(背压队列),队列满时降级丢弃低优先消息。错误恢复采用指数退避重连,并用全局 `process.on('unhandledRejection')` 兜底。”
💡 章节记忆点:面试官最看重的是你能否在 实际代码中合理选用异步模式,并正确处理错误。记住三句话:回调嵌套不可取,Promise 链式来解耦,async/await 加 try/catch 是最终方案。