
文章目录一、基础结构try...catch...finally二、错误对象 Error1. 内置错误类型2. 自定义错误三、主动抛出throw四、不同错误类型的精准捕获五、finally 的妙用六、异步异常捕获1. Promise 的 catch2. async/await try/catch3. 事件循环中的错误七、全局异常捕获兜底防线1. window.onerror2. window.addEventListener(error)3. unhandledrejection 事件在开发中错误不可避免——网络请求失败、用户输入非法、第三方脚本出错……如果放任不管一个未捕获的异常就可能让整个应用白屏崩溃。异常捕获正是赋予我们“预判风险、优雅降级”的能力。JS 提供了丰富的错误处理手段下面逐一解析。一、基础结构try…catch…finally这是处理同步代码异常的核心语法。try{// 尝试执行的代码letdataJSON.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 无能为力后文会详解。二、错误对象 Error1. 内置错误类型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.nameApiError;this.statusCodestatusCode;}}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(b0){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 中执行了 returnfinally 也会在返回值真正交付之前运行。functiongetUser(){showLoading();try{returnfetchData();// 即使这里 returnfinally 仍会执行}catch(e){returndefaultData;}finally{hideLoading();// 必然执行保证 loading 隐藏}}注意如果 finally 中显式 return它会覆盖 try/catch 中的返回值需谨慎。六、异步异常捕获这是前端异常处理中最容易出问题的环节。1. Promise 的 catchPromise 内的错误包括 reject 和运行时错误都会被 catch 捕获不会冒泡到外层同步 try/catch。fetch(/api/user).then(resres.json()).then(data{// 如果这里抛出错误会被后面的 catch 捕获 console.log(data.info);}).catch(err{console.error(请求失败, err);});2. async/await try/catchasync 函数使异步代码看起来像同步因此 try/catch 可以直接捕获 await 表达式的异常。asyncfunctionloadUser(){try{const responseawait fetch(/api/user);const dataawait 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.onerrorfunction(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来实现完善的异常收集。