async函数中try-catch无法捕获业务错误,需封装saferequest函数统一处理网络层(如fetch失败)和业务层(如code≠0)错误,并按类型标记便于上层分流。

直接用 async 函数写请求逻辑时,try-catch 容易漏掉两类关键错误:一是网络异常(如 fetch 失败),二是业务错误(如后端返回 { code: 401, message: "未登录" })。这两类都不触发 JavaScript 异常,仅靠 await + try-catch 是不够的,必须主动校验。
区分错误类型再统一处理
异步请求失败分两层:
-
网络层错误:比如
TypeError: Failed to fetch、DNS 失败、连接超时 —— 这类会被catch捕获 -
业务层错误:比如响应状态码是
401或500,或 JSON 中data.code !== 0—— 这类需手动判断,否则catch完全不触发
封装一个 safeRequest 工具函数
核心是把“发请求 → 检查状态 → 解析数据 → 校验业务码”全部收进一个 async 函数,并在 try 块里完成所有校验:
- 传入的是请求函数(如
() => fetch('/api/user')),不是已执行的 Promise,避免提前触发无法拦截 - 先用
res.ok判断 HTTP 状态是否正常(即200–299) - 再解析 JSON 并检查
data.code === 0,不符合就throw new Error(...) -
catch块统一做日志、上报、用户提示,最后仍throw,方便调用方决定是否二次捕获
适配不同平台的请求 API
同一套逻辑可复用于不同环境:
- Web 用
fetch:直接传() => fetch(url, options) - 小程序用
wx.request:先 Promise 化,再传() => wxRequest({ url }) - Node.js 用
axios或node-fetch:同样包装成返回 Promise 的函数即可
配合全局错误流更省心
如果项目已有统一错误处理机制(如 Express 的 app.use((err, req, res, next) => {...}) 或前端的错误边界组件),safeRequest 只需专注“把业务错误转成标准 Error”,剩下的交由上层分流:
- 网络错误可标记为
err.type = 'network' - 业务错误可附带
err.code = data.code和err.message = data.message - 这样上层能按类型做不同动作:重试、跳登录页、展示友好提示等











