async函数捕获异常的关键在于在try中await每个可能失败的操作,如fetch和res.json(),并手动检查http状态和响应体,配合promise.all或allsettled实现并发容错,且catch需分类处理错误类型。

async 函数里捕获异常,关键不是“用不用 try-catch”,而是“在哪写、包什么、怎么判”。它不像同步代码那样一抛就进 catch,必须配合 await 和明确的错误判断逻辑才能真正兜住问题。
必须把 await 放进 try 块里
await 不是魔法开关,它只是让异步操作“看起来像同步”,但异常仍需主动拦截。只调用 async 函数却不 await,错误根本不会触发当前 try-catch。
- ✅ 正确:在 try 中 await 每个可能失败的操作,比如
await fetch(...)、await res.json() - ❌ 错误:写
fetchData();就结束——Promise 被丢弃,异常变成 unhandled rejection,控制台报错但 catch 完全无效 - 特别注意:
res.json()会抛 SyntaxError(后端返回非 JSON),res.blob()可能因流中断失败,这些都得被 await 包住再 catch
手动检查 HTTP 状态,别依赖 fetch 自动 reject
fetch 只在网络彻底断开时才 reject;404、500 这类响应仍返回 Response 对象,且 res.ok === false。不检查就直接解析,业务可能拿错数据运行。
- 在
await fetch()后立刻判断:if (!res.ok) throw new Error(`HTTP ${res.status}`) - 这样能把语义化错误(如权限不足、资源不存在)转成可捕获的异常,统一进 catch 处理
- 避免只靠 status 判断——有些 API 用 200 返回错误体,这时还需解析 body 后校验 error 字段
多个独立请求别傻等,要并发+分别容错
连续写三个 await 是串行执行:第一个失败,后面两个根本不会发。既慢又脆弱。
- ✅ 独立任务先发起,再并发等待:
const [a, b, c] = await Promise.all([apiA(), apiB(), apiC()]) - ⚠️ 如果某个请求允许失败不影响整体,用
Promise.allSettled替代Promise.all,它返回每个结果的状态(fulfilled/rejected),可单独处理失败项 - ❌ 别写
await apiA(); await apiB(); await apiC();——这不是并发,是排队
catch 里别只打日志,要做分类响应
网络超时、JSON 解析失败、变量未定义,错误类型完全不同。泛化 catch 会让问题难以定位。
- 区分错误类型:
err instanceof TypeError(代码问题)、err.name === 'AbortError'(取消请求)、err.message.includes('failed to fetch')(网络不可达) - 可恢复错误(如临时超时)可重试或降级;不可恢复错误(如语法错误、API 地址拼错)应上报监控并提示用户检查操作
- 避免空 catch:
catch(e) { console.log(e); }会吞掉堆栈和上下文,调试时只剩“undefined is not a function”这种模糊提示











