跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端

前端错误处理实战:try/catch 与 Promise 用法

前端错误处理需区分同步与异步场景。try/catch 仅捕获同步异常,异步错误需用 Promise.catch 或 async/await 包裹。Fetch 请求需手动判断 res.ok 以处理 HTTP 状态码,避免 4xx/5xx 被忽略。JSON 解析应封装安全函数防止崩溃。业务异常与系统异常需分类处理,前者提示用户可操作项,后者上报监控并展示通用提示。规范使用 try/catch 结合 Promise 机制覆盖大部分开发场景。

w795471发布于 2026/4/7更新于 2026/5/219 浏览
前端错误处理实战:try/catch 与 Promise 用法

开篇

前端开发中,错误处理很常见:接口失败、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 的地方

  1. JSON 解析:JSON.parse、res.json() 等容易抛错的地方
  2. 可能抛出异常的第三方库:如日期解析、复杂计算等
  3. 同步的、可能出错的业务逻辑:如参数校验、数据转换等

5.2 不要指望 try/catch 的地方

  1. 异步回调:用 Promise 的 .catch、async/await 的 try/catch 包住 await 那一行
  2. 事件监听:在回调里单独加 try/catch
  3. 全局错误:用 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,关键是区分'可预期业务失败'和'真正的异常',在合适的地方用合适的工具处理。

目录

  1. 开篇
  2. 一、先搞清楚:try/catch 到底能抓到啥
  3. 1.1 能抓到的:同步代码里的异常
  4. 1.2 抓不到的:异步里的错误
  5. 二、Ajax 错误:别只盯着 try/catch
  6. 2.1 fetch 简介
  7. 2.2 常见误解
  8. 2.3 正确做法
  9. 三、JSON 解析错误:最容易漏掉的一类
  10. 3.1 常见场景
  11. 3.2 推荐写法
  12. 四、业务异常 vs 系统异常:分类处理
  13. 4.1 业务异常(可预期的“业务失败”)
  14. 4.2 系统异常(程序/环境错误)
  15. 4.3 实战示例
  16. 五、实战中的几条规范
  17. 5.1 该用 try/catch 的地方
  18. 5.2 不要指望 try/catch 的地方
  19. 5.3 一个完整的小案例
  20. 六、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • MySQL 数据类型详解与应用实践
  • Python 代码打包为 EXE 完全指南
  • Python 基础语法、数据类型与模块实战
  • Hibernate 集合映射
  • Web3 核心概念解析与比特币以太坊对比
  • ToDesk 推出 ToClaw:AI 助手可直接操作电脑
  • Moltbot 集成钉钉 Stream 流式接入配置指南
  • C++ 标准库 string 类全面指南
  • 华为机试题解:素数伴侣(最大二分图匹配)
  • Spring Boot Web 后端开发核心注解
  • Qwen-Multiple-Angles:基于 Qwen-Image-Edit 的多视角生成插件实战
  • OpenVINO 优化 Stable Diffusion 实现边缘设备高效推理
  • LLaMA-Factory 多 GPU 微调加速指南
  • MySQL Online DDL 三大算法 INSTANT、INPLACE、COPY 差异详解
  • C++ std::vector 动态数组核心用法与原理
  • Ubuntu 22.04 安装后启动卡死问题解决方案
  • GitHub、谷歌学术与 Sci-Hub 镜像站使用指南及实测分析
  • OpenClaw 推动低代码 AI 从工具赋能到生态重构
  • C++ STL 容器 string 的遍历方法
  • Agent Skills:构建可扩展 AI 代理能力的模块化架构

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online