JavaScript异常捕获的完全指南

 更新时间:2026年07月26日 14:50:10   作者:_AidenSun  
在开发中,错误不可避免——网络请求失败、用户输入非法、第三方脚本出错……如果放任不管,一个未捕获的异常就可能让整个应用白屏崩溃,JS 提供了丰富的错误处理手段,下面逐一解析,需要的朋友可以参考下

引言

在开发中,错误不可避免——网络请求失败、用户输入非法、第三方脚本出错……如果放任不管,一个未捕获的异常就可能让整个应用白屏崩溃。异常捕获正是赋予我们“预判风险、优雅降级”的能力。JS 提供了丰富的错误处理手段,下面逐一解析。

一、基础结构:try…catch…finally

这是处理同步代码异常的核心语法。

try {
  // 尝试执行的代码
  let data = JSON.parse(jsonStr);
} catch (error) {
  // 当 try 块中抛出错误时执行
  console.error('解析失败:', error.message);
} finally {
  // 无论是否出错,最终都会执行
  console.log('清理临时变量、关闭连接等');
}

执行流程:

1、执行 try 中的代码。

2、如果没有异常,跳过 catch,执行 finally。

3、如果抛出异常,try 中后续代码立即停止,进入 catch;执行完catch 后再进入 finally。

4、finally 即使在 try 或 catch 中有 return,也依然会执行(在真正返回前执行)。

注意:catch 捕获的必须是 try 块中同步执行时抛出的错误。若是异步回调中的错误(如 setTimeout),外层 try/catch 无能为力,后文会详解。

二、错误对象 Error

1. 内置错误类型

JS 内置了多种错误构造函数,可通过 instanceof 区分:

1、Error —— 通用错误

2、SyntaxError —— 语法错误

3、ReferenceError —— 引用错误(变量不存在)

4、TypeError —— 类型错误

5、RangeError —— 数值超出范围

6、URIError —— URI 处理函数错误

每种错误都包含 name、message、stack 等属性。stack 记录了调用栈,是调试的利器。

2. 自定义错误

扩展 Error 类可以创建业务专用错误,携带更多上下文信息。

class ApiError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.name = 'ApiError';
    this.statusCode = statusCode;
  }
}

try {
  throw new ApiError('Not Found', 404);
} catch (err) {
  if (err instanceof ApiError) {
    console.error(`API 错误 ${err.statusCode}: ${err.message}`);
  }
}

三、主动抛出:throw

任何值都可以被 throw(但推荐抛出 Error 对象),它能够中断当前执行流,并沿着调用栈向上传播,直到被 catch 捕获。

function divide(a, b) {
  if (b === 0) {
    throw new Error('除数不能为零');
  }
  return a / b;
}

四、不同错误类型的精准捕获

catch 块可以结合 instanceof 或 error.name 来做分类处理。

try {
  // 可能抛出多种错误的代码
} catch (err) {
  if (err instanceof TypeError) {
    // 处理类型错误
  } else if (err instanceof RangeError) {
    // 处理范围错误
  } else {
    // 其他未知错误重新抛出
    throw err;
  }
}

重新抛出是一个重要技巧:只处理你预期的错误,未预料的错误继续向上抛给上层逻辑。

五、finally 的妙用

finally 适合放“必须执行”的清理代码,比如关闭文件流、清除定时器、隐藏 loading 效果等。即使 try 或 catch 中执行了 return,finally 也会在返回值真正交付之前运行。

function getUser() {
  showLoading();
  try {
    return fetchData();  // 即使这里 return,finally 仍会执行
  } catch (e) {
    return defaultData;
  } finally {
    hideLoading();      // 必然执行,保证 loading 隐藏
  }
}

注意:如果 finally 中显式 return,它会覆盖 try/catch 中的返回值,需谨慎。

六、异步异常捕获

这是前端异常处理中最容易出问题的环节。

1. Promise 的 catch

Promise 内的错误(包括 reject 和运行时错误)都会被 catch 捕获,不会冒泡到外层同步 try/catch。

fetch('/api/user')
  .then(res => res.json())
  .then(data => {
    // 如果这里抛出错误,会被后面的 catch 捕获
    console.log(data.info);
  })
  .catch(err => {
    console.error('请求失败:', err);
  });

2. async/await + try/catch

async 函数使异步代码看起来像同步,因此 try/catch 可以直接捕获 await 表达式的异常。

async function loadUser() {
  try {
    const response = await fetch('/api/user');
    const data = await response.json();
    return data;
  } catch (err) {
    console.error('加载用户失败', err);
    // 返回降级数据或重新抛出
    return { name: '匿名用户' };
  }
}

重要:await 会将 Promise 的 reject 转化为同步异常,所以 try/catch 有效。但别忘了 async 函数自身返回的是 Promise,调用方也需要处理可能的异常。

3. 事件循环中的错误

setTimeout、setInterval 等回调在下一个事件循环中执行,外层的 try/catch 完全无效。

try {
  setTimeout(() => {
    throw new Error('定时器错误'); // 全局异常,外层 try 捕获不到
  }, 1000);
} catch (e) {
  // 不会执行
}

正确的做法是在回调内部自行 try/catch,或依赖全局异常捕获机制。

七、全局异常捕获(兜底防线)

即使项目代码再完善,仍可能有遗漏的未捕获异常。浏览器提供了全局监听手段,用于错误上报与友好提示。

1. window.onerror

捕获全局同步运行时错误(除 Promise 外)。

window.onerror = function(message, source, lineno, colno, error) {
  console.error('全局错误捕获:', message, 'at', source, lineno);
  // 上报到监控平台
  return true; // 返回 true 可阻止浏览器默认报错行为
};

2. window.addEventListener(‘error’)

更强大的监听,可以捕获资源加载失败(如 404、脚本加载失败)以及运行时错误(比 onerror 稍晚触发,但信息更全)。

window.addEventListener('error', (event) => {
  if (event.target instanceof HTMLImageElement) {
    console.error('图片加载失败:', event.target.src);
  } else {
    console.error('运行时错误:', event.message);
  }
}, true); // 使用捕获阶段,因为资源错误不冒泡

3. unhandledrejection 事件

专用于捕获未被 .catch() 或 try/catch 处理的 Promise 拒绝。

window.addEventListener('unhandledrejection', event => {
  console.error('未处理的 Promise 拒绝:', event.reason);
  // 可以调用 event.preventDefault() 防止控制台默认报错
});

现代前端监控体系通常会结合这三种全局事件 + 框架级错误边界(如 React Error Boundary)来实现完善的异常收集。

以上就是JavaScript异常捕获的完全指南的详细内容,更多关于JavaScript异常捕获的资料请关注脚本之家其它相关文章!

相关文章

  • javascript 数组精简技巧小结

    javascript 数组精简技巧小结

    本文给大家分享了13个非常常用的JavaScript数组操作的小技巧,有需要的小伙伴可以来看看,个人十分推荐.
    2020-02-02
  • javascript生成随机数的方法

    javascript生成随机数的方法

    这篇文章主要介绍了javascript生成随机数的方法,需要的朋友可以参考下
    2014-05-05
  • 浅谈layui 数据表格前后台传值的问题

    浅谈layui 数据表格前后台传值的问题

    今天小编就为大家分享一篇浅谈layui 数据表格前后台传值的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • JS字节数组转数字及数字转字节数组的方法

    JS字节数组转数字及数字转字节数组的方法

    本文将深入解析长整数与字节数组互转的技术原理,提供ES6(现代浏览器/Node.js)与ES5(兼容旧环境)两套实现方案,感兴趣的朋友一起看看吧
    2025-04-04
  • JS实现仿Windows经典风格的选项卡Tab切换代码

    JS实现仿Windows经典风格的选项卡Tab切换代码

    这篇文章主要介绍了JS实现仿Windows经典风格的选项卡Tab切换代码,涉及JavaScript元素的遍历与样式的修改技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • js清空表单数据的两种方式(遍历+reset)

    js清空表单数据的两种方式(遍历+reset)

    这篇文章主要介绍了js清空表单数据的两种方式(遍历+reset),需要的朋友可以参考下
    2014-07-07
  • JavaScript Typescript基础使用教程

    JavaScript Typescript基础使用教程

    TypeScript是Microsoft(微软)开发的一种开源编程语言,它充分利用了JavaScript原有的对象模型,并在此基础上进行了扩充,TypeScript设计目标是开发大型应用,它可以编译成纯JavaScript,编译出来的JavaScript可以运行在任何一种JS运行环境中
    2022-12-12
  • 微信小程序骨架屏的实现方法

    微信小程序骨架屏的实现方法

    本文主要介绍了微信小程序骨架屏的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • 删除javascript中注释语句的正则表达式

    删除javascript中注释语句的正则表达式

    这篇文章主要介绍了删除javascript中注释语句的正则表达式,需要的朋友可以参考下
    2014-06-06
  • webpack-dev-server搭建本地服务器的实现

    webpack-dev-server搭建本地服务器的实现

    当我们使用webpack打包时,发现每次更新了一点代码,都需要重新打包,我们希望本地能搭建一个服务器,本文就介绍如何使用webpack-dev-server搭建本地服务器,感兴趣的可以了解一下
    2021-07-07

最新评论