关键在于逻辑清晰、错误可控、执行高效:优先用async/await替代嵌套Promise链,合理使用Promise.all/allSettled并发请求,严格处理超时重试与错误上下文,避免隐式串行和错误静默。

写好 JavaScript 异步代码,关键不是堆砌语法,而是让逻辑清晰、错误可控、执行高效。真正容易出问题的地方,往往藏在看似“能跑通”的写法里。
用 async/await 统一异步流程
避免嵌套 .then().catch() 链,尤其当步骤超过三层时,可读性和调试难度会陡增。async/await 不仅是语法糖,它让执行顺序一目了然,也天然支持同步式错误捕获。
- 函数必须声明为 async,内部才能使用 await
- 每个 await 后面的表达式应返回 Promise;非 Promise 值会被自动包装成 resolved 状态
- 用 try/catch 包裹整个业务块,比分散的 .catch() 更易定位失败环节
- 顶层 await 在 ES2022+ 模块中可用,但不建议在非模块环境或全局作用域滥用
并发请求优先用 Promise.all 或 allSettled
多个独立接口(比如拉用户信息、配置项、权限列表)不该串行等待,而应并行发起。串行写法会让总耗时等于各请求时间之和,而并发可压缩到最长那个请求的时间。
- Promise.all:全部成功才 resolve,任一失败即 reject,适合强一致性场景
- Promise.allSettled:等所有 Promise 结束,返回每个结果的状态对象,适合容错聚合
- 别在 for 循环里直接 await 请求——那是隐式串行,性能损失明显
- 批量请求前,先 collect 所有 Promise,再统一 await Promise.all([…])
主动控制超时与重试逻辑
网络请求不能无限等待,也不能一失败就放弃。超时和重试不是“锦上添花”,而是健壮性的基本要求。
立即学习“Java免费学习笔记(深入)”;
- 用 Promise.race 包装 fetch + 定时 reject,实现请求级超时
- 重试逻辑建议封装成独立函数(如 retry(fn, times = 3)),避免每处重复写 setTimeout 或递归
- 超时错误和业务错误要区分处理:前者提示“网络不稳定”,后者提示具体业务原因
- 避免在重试中盲目 await sleep,应结合指数退避(exponential backoff)降低服务压力
错误处理要具体且可追溯
Promise.reject(‘失败’) 这类字符串拒绝,会让排查变得困难。错误信息需要携带上下文、堆栈和类型标识。
- 始终用 new Error(…) 构造拒绝原因,便于 DevTools 展开堆栈
- catch 中不要只 console.error,应根据错误类型做差异化响应(如 401 跳登录,503 提示重试)
- 全局监听 unhandledrejection 可用于兜底日志,但不能替代局部 try/catch
- 避免在 Promise 构造器中 return 值或传入 async 回调——这会导致错误丢失或状态不可控
不复杂但容易忽略:异步代码的质量,不在它“能不能跑”,而在它“出错时是否说得清”、“并发时是否扛得住”、“维护时是否看得懂”。选对模式,守住边界,比炫技更重要。
文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/jiquanzatan/123647.html