当前位置: 首页 > news >正文

JavaScript 异常捕获完全指南

文章目录

  • 一、基础结构:try...catch...finally
  • 二、错误对象 Error
    • 1. 内置错误类型
    • 2. 自定义错误
  • 三、主动抛出:throw
  • 四、不同错误类型的精准捕获
  • 五、finally 的妙用
  • 六、异步异常捕获
    • 1. Promise 的 catch
    • 2. async/await + try/catch
    • 3. 事件循环中的错误
  • 七、全局异常捕获(兜底防线)
    • 1. window.onerror
    • 2. window.addEventListener('error')
    • 3. unhandledrejection 事件

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

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

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

try{// 尝试执行的代码letdata=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 捕获。

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

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

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

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

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

五、finally 的妙用

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

functiongetUser(){showLoading();try{returnfetchData();// 即使这里 return,finally 仍会执行}catch(e){returndefaultData;}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 表达式的异常。

asyncfunctionloadUser(){try{const response=await fetch('/api/user');const data=await response.json();returndata;}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);// 上报到监控平台returntrue;// 返回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)来实现完善的异常收集。

http://www.cnnetsun.cn/news/3508308.html

相关文章:

  • Ubuntu 22.04编译AOSP Android 13完整指南
  • Wallpaper Engine资源逆向全解析:3步掌握PKG解密与TEX纹理转换技术
  • Winform多线程UI操作简化与优化实践
  • 【mimo-硬件损伤-预编码】加权融合预编码 —— 从“单项冠军”到“全能战队”
  • Unity与VS2013/2015调试集成:原理、配置与实战排错指南
  • CANoe CAPL中Checksum与Counter的实现与应用
  • WAIC 2026|范式展出全栈 AI 底座与产业落地成果,构筑 AI 2.0 Token 工厂
  • 多模型网关 Token 账单对不上:流式响应、重试与团队成本归因的实现
  • ShaderGraph沃罗诺伊噪声:从原理到实战,打造程序化纹理与材质
  • 安卓网络请求框架android-async-http详解与优化实践
  • ShaderGraph三角波节点深度解析:从数学原理到UI动效与游戏特效实战
  • ASP.NET Core Identity高级定制与安全实践
  • 支持JavaScript基础语法和数据类型,以及数组、集合、字典、对象操作。 支持require引用模块。 二、安装 1 install-package AScript 2 install-pac
  • Python新手入门:环境搭建与基础语法详解
  • 博客导航系统设计:提升老文章阅读量的技术方案
  • C++多线程编程:跨平台互斥锁原理与实战指南
  • AI自动化不是写脚本,而是重构工程思维:资深架构师拆解4层抽象模型与交付验收标准
  • 期末作业(1)
  • 2026年权威榜单安全触边装置推荐,助你提升工业安全性
  • 2021年Android面试趋势与核心技术解析
  • 3个简单步骤彻底告别键盘连击烦恼:让老旧机械键盘重获新生
  • FPGA实时4K超分辨率方案:Agilex7硬件加速AI视频处理实践
  • 为什么ORACLE使用JDBC查询SYSDATE时,RS.getDate能获取到时间部分?
  • AM62L CBASS硬件防火墙配置实战:从寄存器解析到多域安全策略
  • 污水提升泵售后哪家强?看准这三点不踩坑
  • Ofd2Pdf:5分钟掌握OFD转PDF的本地化高效解决方案
  • 策略从研究端迁到券商端:字段映射、权限和订单回报逐项核对
  • SDRAM控制器子系统:防火墙、VRFB与调度器深度解析
  • Node.js核心价值与六大实战场景深度解析
  • 20260718_143934 课程头图