欢迎光临
我们一直在努力

try/catch/Promise:前端错误处理实战|JS 基础语法与数据操作篇

【try/catch/Promise】+【前端错误处理】:从【异常捕获逻辑】到【落地实操】,彻底搞懂前端错误处理的最佳写法,避开异步捕获、HTTP状态码判断高频坑!

📑 文章目录

  • 开篇
  • 一、先搞清楚:try/catch 到底能抓到啥
    • 1.1 能抓到的:同步代码里的异常
    • 1.2 抓不到的:异步里的错误
  • 二、Ajax 错误:别只盯着 try/catch
    • 2.1 fetch 是什么?小白必读
    • 2.2 常见误解
    • 2.3 正确做法
  • 三、JSON 解析错误:最容易漏掉的一类
    • 3.1 常见场景
    • 3.2 推荐写法
  • 四、业务异常 vs 系统异常:分类处理
    • 4.1 业务异常(可预期的“业务失败”)
    • 4.2 系统异常(程序/环境错误)
    • 4.3 实战示例
  • 五、实战中的几条规范
    • 5.1 该用 try/catch 的地方
    • 5.2 不要指望 try/catch 的地方
    • 5.3 一个完整的小案例
  • 六、总结
  • 🔍 本系列专栏导航

同学们好,我是 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(() => {
throw new Error('异步报错'); // 这个 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 = await fetch('/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 = await fetch('/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 状态异常”:

async function fetchUserList() {
try {
const res = await fetch('/api/user/list');

if (!res.ok) {
throw new Error(`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,否则手动 throw

  • res.json() 可能抛 JSON 解析错误,会被 catch 捕获

  • 网络类错误在 catch 里单独分支处理

⬆ 返回目录


三、JSON 解析错误:最容易漏掉的一类

3.1 常见场景

后端返回的是字符串,或者格式不对:

// 后端返回: "用户不存在"(纯字符串)
// 或者返回: {data: invalid}(非法 JSON)
const data = JSON.parse(response); // 直接崩

JSON.parse 抛的是 SyntaxError,如果不包一层 try/catch,会直接导致整段脚本报错,甚至影响后续逻辑。

⬆ 返回目录

3.2 推荐写法

function safeParse(str, fallback = null) {
try {
return JSON.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 实战示例

async function placeOrder(orderData) {
try {
const res = await fetch('/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/5xx
return { success: false, type: 'system', message: data?.message || '服务器异常,请稍后重试' };
}

return { success: true, data };

} catch (e) {
// 系统异常:网络错误、JSON 解析异常等
reportError(e); // 上报监控
return { success: false, type: 'system', message: '网络异常,请检查网络后重试' };
}
}

调用方可以这样区分:

const result = await placeOrder(formData);

if (result.success) {
// 跳转支付/成功页
} else if (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 一个完整的小案例

    async function getProductDetail(id) {
    try {
    const res = await fetch(`/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' };
    }
    throw new Error(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,关键是区分“可预期业务失败”和“真正的异常”,在合适的地方用合适的工具处理。

    ⬆ 返回目录


    🔍 本系列专栏导航

    一、《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 基础语法与数据操作篇》

    👉 跟着系列慢慢学,把技术功底扎扎实实地打牢~

    ⬆ 返回目录


    学习本就是一场持久战,不需要急着一口吃成胖子。哪怕今天你只记住了一点点,这都是实打实的进步。

    后续我还会继续用这种大白话、讲实战方式,带大家扫盲更多前端基础。

    关注我,不迷路,咱们把那些曾经模糊的知识点,一个个彻底搞清楚。

    如果你觉得这篇内容对你有帮助,不妨点赞+收藏,下次写代码卡壳时,拿出来翻一翻,比搜引擎更靠谱。

    我是 Eugene,你的电子学友,我们下一篇干货见~

    赞(0)
    未经允许不得转载:171主机测评 » try/catch/Promise:前端错误处理实战|JS 基础语法与数据操作篇
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址