try/catch/Promise:前端错误处理实战|JS 基础语法与数据操作篇
【try/catch/Promise】+【前端错误处理】:从【异常捕获逻辑】到【落地实操】,彻底搞懂前端错误处理的最佳写法,避开异步捕获、HTTP状态码判断高频坑!
📑 文章目录
- 开篇
- 一、先搞清楚:
try/catch到底能抓到啥 - 二、
Ajax错误:别只盯着try/catch - 三、JSON 解析错误:最容易漏掉的一类
- 四、业务异常 vs 系统异常:分类处理
- 五、实战中的几条规范
- 六、总结
- 🔍 系列模块导航
同学们好,我是 Eugene(尤金),一个拥有多年中后台开发经验的前端工程师~
(Eugene 发音很简单,/juːˈdʒiːn/,大家怎么顺口怎么叫就好)
你是否也有过:明明学过很多技术,一到关键时候却讲不出来、甚至写不出来?
你是否也曾怀疑自己,是不是太笨了,明明感觉会,却总差一口气?
就算想沉下心从头梳理,可工作那么忙,回家还要陪伴家人。
一天只有24小时,时间永远不够用,常常感到力不从心。
技术行业,本就是逆水行舟,不进则退。
如果你也有同样的困扰,别慌。
从现在开始,跟着我一起心态归零,利用碎片时间,来一次彻彻底底的基础扫盲。
这一次,我们一起慢慢来,扎扎实实变强。
不搞花里胡哨的理论堆砌,只分享看得懂、用得上的前端干货,
咱们一起稳步积累,真正摆脱“面向搜索引擎写代码”的尴尬。
开篇
前端开发中,错误处理很常见:接口失败、JSON 解析报错、业务失败和系统异常混在一起处理。不少人要么到处 try/catch,要么该用的地方没用,导致线上问题难排查、用户提示不友好。
用原生 try/catch 配合 Promise/async 的错误处理就能覆盖大部分场景。本文结合真实项目中的常见需求,说明什么时候用 try/catch、什么时候用 .catch()、业务异常和系统异常如何区分,只讲日常开发里 80% 会用到的情况。
一、先搞清楚:try/catch 到底能抓到啥
很多人的第一反应是:try/catch 能把“所有报错”都包住。实际上不是。
1.1 能抓到的:同步代码里的异常
try{const obj =JSON.parse('{ invalid json }');// 抛出 SyntaxError console.log(obj);}catch(e){ console.error('解析失败:', e.message);// 能抓到}只要错误是在同步代码里抛出的,就会被 catch 捕获。
1.2 抓不到的:异步里的错误
try{setTimeout(()=>{thrownewError('异步报错');// 这个 catch 抓不到!},0);}catch(e){ console.error(e);// 不会执行}setTimeout 的回调在下一个事件循环执行,执行时 try 早就结束了,所以这里的 catch 完全接不到这个错误。
同理,Promise 内部的 reject、Ajax 的失败回调等异步错误,也不能被外层的 try/catch 直接捕获,需要用别的方式处理。
二、Ajax 错误:别只盯着 try/catch
2.1 fetch 是什么?小白必读
在讲 Ajax 错误之前,先简单说一下 fetch 是什么,这样后面的代码你才能看得懂。
一句话:fetch 是浏览器自带的、用来向服务器发请求、拿数据的 API。
可以把它理解成:
- 你:在浏览器里打开页面,想拿到用户列表、商品信息等
- 服务器:数据放在后端,需要通过「请求」才能给你
- fetch:就是你发请求、等回复的「工具」
最基础的用法:
// 向 /api/user/list 这个地址发一个「我要数据」的请求const res =awaitfetch('/api/user/list');const data =await res.json();// 把服务器返回的文本解析成 JSON 对象 console.log(data);// 拿到数据了几个关键点:
| 概念 | 大白话解释 |
|---|---|
fetch(地址) | 向这个地址发请求,默认是 GET(取数据) |
| 返回值 | 是一个 Promise,所以要用 await 等它完成 |
res | 服务器返回的「响应对象」,里面有状态码、响应体等 |
res.json() | 把响应体当成 JSON 解析,返回一个 JS 对象 |
res.text() | 把响应体当成普通文本,返回字符串 |
和 Ajax 的关系: 以前大家用 XMLHttpRequest 或 jQuery 的 $.ajax 来发请求,fetch 是浏览器后来提供的、更简单的新方式,本质做的都是同一件事:从浏览器向服务器发请求、拿数据。
搞懂这些后,下面就能理解为什么 fetch 的错误处理和你想的不太一样了。
2.2 常见误解
有人会这样写:
try{const res =awaitfetch('/api/user/list');const data =await res.json();return data;}catch(e){ console.error('请求失败', e);}这里有个关键点:HTTP 4xx/5xx 并不会让 fetch 抛出异常,只有网络失败、跨域等才会抛。所以:
- 404、500 等错误 → 不会被
catch捕获 - 网络断开、超时 → 会被捕获
2.3 正确做法
要同时处理“网络/请求异常”和“HTTP 状态异常”:
asyncfunctionfetchUserList(){try{const res =awaitfetch('/api/user/list');if(!res.ok){thrownewError(`HTTP ${res.status}: ${res.statusText}`);}const data =await res.json();return data;}catch(e){if(e.name ==='TypeError'&& e.message.includes('fetch')){ console.error('网络异常,请检查网络');}else{ console.error('请求失败:', e.message);}throw e;// 让调用方也知道失败了}}要点:
res.ok判断 2xx,否则手动throwres.json()可能抛 JSON 解析错误,会被catch捕获- 网络类错误在
catch里单独分支处理
三、JSON 解析错误:最容易漏掉的一类
3.1 常见场景
后端返回的是字符串,或者格式不对:
// 后端返回: "用户不存在"(纯字符串)// 或者返回: {data: invalid}(非法 JSON)const data =JSON.parse(response);// 直接崩JSON.parse 抛的是 SyntaxError,如果不包一层 try/catch,会直接导致整段脚本报错,甚至影响后续逻辑。
3.2 推荐写法
functionsafeParse(str, fallback =null){try{returnJSON.parse(str);}catch(e){ console.warn('JSON 解析失败:', e.message,'原始内容:', str?.slice(0,50));return fallback;}}const data =safeParse(response,{});思路:
- 解析失败时返回一个兜底值(如
{}或[]),而不是让程序直接崩溃 - 打
warn方便排查问题 - 把解析逻辑封装成
safeParse,减少重复代码
四、业务异常 vs 系统异常:分类处理
很多人把所有错误都当成“失败”来处理,不做区分,交互和排查都会受影响。
4.1 业务异常(可预期的“业务失败”)
- 比如:余额不足、未登录、参数错误、权限不足等
- 通常由后端通过 HTTP 状态码 + 业务码 + 消息返回
- 需要展示给用户,并做相应业务流程处理
4.2 系统异常(程序/环境错误)
- 比如:网络断开、服务器 500、JSON 解析失败、未捕获的运行时错误
- 多半需要上报、告警,用户只看到通用错误提示
4.3 实战示例
asyncfunctionplaceOrder(orderData){try{const res =awaitfetch('/api/order/create',{method:'POST',body:JSON.stringify(orderData),});const text =await res.text();const data =safeParse(text,null);if(!res.ok){// 业务异常:有明确的业务码和提示if(data?.code ==='BALANCE_INSUFFICIENT'){return{success:false,type:'business',message:'余额不足,请先充值'};}if(data?.code ==='UNAUTHORIZED'){return{success:false,type:'auth',message:'请先登录'};}// 其他 4xx/5xxreturn{success:false,type:'system',message: data?.message ||'服务器异常,请稍后重试'};}return{success:true, data };}catch(e){// 系统异常:网络错误、JSON 解析异常等reportError(e);// 上报监控return{success:false,type:'system',message:'网络异常,请检查网络后重试'};}}调用方可以这样区分:
const result =awaitplaceOrder(formData);if(result.success){// 跳转支付/成功页}elseif(result.type ==='business'|| result.type ==='auth'){ message.warning(result.message);// 业务提示,用户可操作}else{ message.error(result.message);// 系统异常,建议稍后重试}五、实战中的几条规范
5.1 该用 try/catch 的地方
- JSON 解析:
JSON.parse、res.json()等容易抛错的地方 - 可能抛出异常的第三方库:如日期解析、复杂计算等
- 同步的、可能出错的业务逻辑:如参数校验、数据转换等
5.2 不要指望 try/catch 的地方
- 异步回调:用
Promise的.catch、async/await的try/catch包住await那一行 - 事件监听:在回调里单独加
try/catch - 全局错误:用
window.onerror或unhandledrejection做兜底
5.3 一个完整的小案例
asyncfunctiongetProductDetail(id){try{const res =awaitfetch(`/api/product/${id}`);const text =await res.text();const data =safeParse(text);if(!res.ok){if(data?.code ==='NOT_FOUND'){return{ok:false,reason:'product_not_found'};}thrownewError(data?.message ||`请求失败: ${res.status}`);}return{ok:true, data };}catch(e){if(e.name ==='SyntaxError'){reportError(e,{context:'JSON解析', id });return{ok:false,reason:'parse_error'};}if(e.message?.includes('fetch')|| e.message?.includes('Network')){return{ok:false,reason:'network_error'};}throw e;}}六、总结
| 错误类型 | 处理方式 | 注意点 |
|---|---|---|
Ajax 网络错误 | try/catch + res.ok 判断 | 4xx/5xx 不会自动抛异常 |
JSON 解析错误 | 对 JSON.parse 包 try/catch | 建议封装 safeParse |
| 业务异常 | 根据 code 分支,返回固定结构 | 给用户明确提示 |
| 系统异常 | catch 后上报 + 通用提示 | 避免暴露内部错误细节 |
| 异步错误 | Promise .catch / async try | 不要指望外层同步 try 捕获 |
记住:不是所有错误都要用 try/catch,关键是区分“可预期业务失败”和“真正的异常”,在合适的地方用合适的工具处理。
🔍 系列模块导航
📝 JS 基础语法与数据操作
一、《var/let/const:变量与作用域实战选型|JS 基础语法与数据操作篇》
二、《this、箭头函数与普通函数:前端实战避坑指南 | JS 基础语法与数据操作篇》
三、《对象解构赋值:接口数据解包 10 个实战写法|JS 基础语法与数据操作篇》
四、《map/filter/reduce:数组10个常用实战操作|JS 基础语法与数据操作篇》
五、《find/some/every/includes:数组查找与判断实战用法|JS 基础语法与数据操作篇》
六、《sort/localeCompare:对象数组排序与分组实战|JS 基础语法与数据操作篇》
七、《模板字符串 /split/join/ 正则:字符串处理实战|JS 基础语法与数据操作篇》
八、《Date/dayjs:日期时间处理实战|JS 基础语法与数据操作篇》
九、《try/catch/Promise:前端错误处理实战|JS 基础语法与数据操作篇》
十、《import/export:前端模块化实战|JS 基础语法与数据操作篇》
👉 跟着系列慢慢学,把技术功底扎扎实实地打牢~
📚 系列总览
前端体系化学习完全体:基础 → 规范 → 架构 → 大厂面试
四套系列、百余篇高质量实战文,从入门到进阶,一站式补齐前端核心能力
- 前端基础实战系列: 《前端基础实战:JS/TS与Vue体系化扫盲(47 篇完整目录 + 避坑)》
- 前端规范实战系列:工程化编码规范 + API / 交互 / 组件统一标准(持续更新中)
- 前端架构实战系列:聚焦工程化、性能优化、可维护架构、中后台体系设计(规划中)
- 前端大厂面试系列:覆盖高频考点、手写题、项目深挖、简历与面试技巧(规划中)
每个系列完结后,都会整理成一篇完整导航文并附上直达链接,方便大家按顺序、体系化学习。
全套内容持续更新中,敬请期待~
学习本就是一场持久战,不需要急着一口吃成胖子。哪怕今天你只记住了一点点,这都是实打实的进步。
后续我还会继续用这种大白话、讲实战方式,带大家扫盲更多前端基础。
关注我,不迷路,咱们把那些曾经模糊的知识点,一个个彻底搞清楚。
如果你觉得这篇内容对你有帮助,不妨点赞+收藏,下次写代码卡壳时,拿出来翻一翻,比搜引擎更靠谱。
我是 Eugene,你的电子学友,我们下一篇干货见~