聊一聊前端日常使用的try...catch...finally

一、基本概念

try/catch 是 JavaScript 的异常处理机制,用于捕获代码执行中的错误,防止程序因未处理异常而崩溃。基本结构如下:

js 复制代码
try { 
// 可能抛出错误的代码
} catch (error) {
// 异常处理逻辑
} finally {
// 无论是否出错都会执行的代码(可选)
}
  • try 块:包裹可能引发异常的代码,如网络请求、数据解析等。
  • catch 块 :捕获异常,error 参数包含错误信息(如 message, stack)。
  • finally 块:用于释放资源或执行清理操作(如关闭文件、重置状态)

二、错误类型分类与处理

1、内置的错误类型

javascript提供多种内置的错误类型,常见包括

  • Error通用错误类型
  • SyntaxError语法错误,比如未闭合的标签。
  • TypeError类型错误,比如调用不存在的方法
  • ReferenceError引用错误,比如访问未定义的变量。
  • 自定义错误 :通过 throw new Error("自定义消息") 抛出

2、判断错误的类型

通过instanceof区分错误类型,实现精细化处理

js 复制代码
try{
  //...
}catch(error){
  if(error instanceof TypeError){
    console.log('类型错误', error.message)
  }else if(error instanceof SyntaxErroe){
    console.log('语法错误', error.stack)
  }
}

三、异步场景下的异常处理

1、Promise链式调用

  • 同步错误:try/catch可直接捕获async/await中的错误
js 复制代码
async function fetchData(){
  try{
    const res = await fetch('api/getdata.do');
    const data = await res.json();
  }catch(error){
    console.error("请求失败:", error);
  }
}
  • 异步错误:异步宏任务/微任务 setTimeout或者是原生的Promise需要在内部处理错误,因为外层的try/catch无法捕获异步回调。
js 复制代码
fetch('api/getdata.do').then(result){
  //...
}.catch(error){
 //...
}

2、异步错误捕获示例

js 复制代码
// 正确做法:在异步函数内部处理 
setTimeout(() => {
  try { throw new Error("已捕获的异步错误");
} catch (error) {
  console.error(error);
  }
}, 1000);

3、useEffect内部错误的捕获

如果我们直接用 try/catch 包裹 useEffect 去捕获他内部的错误是无法生效的,因为 useEffect 是异步调用的,他会在组件渲染之后才会执行,但是 try/catch 是同步执行的,所以从 try/catch 的角度来看都是成功的,因此为了捕获 useEffect 内部的错误,try/catch 也应该放在里面,代码示例

js 复制代码
useEffect(() => {
  try { throw new Error('balabala');
} catch(e) {
  // 对异常做一些处理
  }
}, [])

四、前端框架中的应用

1、vue.js

  • watch 监听器 :在数据变化处理逻辑中包裹 try/catch,防止因异常导致组件崩溃:
js 复制代码
watch: {
  dataKey(newVal) { 
  try { 
    // 复杂逻辑或外部 API 调用 
  } catch (error) {
    this.$toast.error("操作失败"); 
    }
  }
}

2、React

  • 错误边界(Error Boundaries) :通过生命周期方法捕获子组件树错误,需结合 try/catch 实现局部容错:(可以捕获 useEffect 以及子组件中的错误,但它不会捕获异步代码和事件处理程序中的错误)
js 复制代码
class ErrorBoundary extends React.Component {
  componentDidCatch(error, info) {
    console.error("组件错误:", error); 
  } render() {
    return this.props.children; 
  } 
}
  • Hooks 中的错误处理 :在 useEffect 内部使用 try/catch
js 复制代码
useEffect(() => {
  try { 
    fetchData(); 
  } catch (error) {
    setErrorState(true); 
  } 
}, [])

五、最佳实践与常见误区

  1. 避免滥用:仅处理可预测的异常(如网络请求,数据解析,调用返回的不确定的数据时)
  2. 错误日志:在catch中记录错误信息(如发送至监控平台)
  3. finally的使用:清理资源(关闭loading状态), 释放资源等
  4. 不要忽略错误,空catch块会存在隐藏问题,需至少记录错误

六、举个try/catch使用的🌰

1、背景

电商平台支付功能,用户提交订单后需要调用第三方支付接口(如支付宝/微信支付)。支付流程涉及网络请求、异步回调、支付状态轮询等操作,任何一个环节出错都可能导致支付失败。以下是使用 try/catch 解决支付异步请求异常的案例。

2、 问题分析

  1. 网络请求不稳定:用户点击支付按钮后,前端需要调用后端接口获取支付凭证。若网络中断或接口超时,需捕获错误并提示用户。
  2. 第三方支付回调异常:支付成功后,第三方平台可能异步通知失败(如回调地址不可达)。
  3. 支付状态轮询失败:前端需轮询后端以确认支付结果,若轮询接口异常需终止流程。

3、解决方案与代码实现

使用 try/catch 处理支付请求与状态轮询

js 复制代码
// React 项目中的支付按钮逻辑 async function handlePayment(orderId) { 
  try { 
    // 1. 显示加载状态 
    setLoading(true); 
    // 2. 获取支付凭证(可能因网络中断或服务端错误失败) 
    const { paymentToken } = await fetchPaymentToken(orderId);     // 3. 调用第三方支付SDK(如支付宝) 
    const result = await thirdPartyPaymentSDK(paymentToken);       // 4. 轮询支付结果(可能因轮询超时失败) 
    await pollPaymentStatus(orderId, 5000); // 5秒超时 
    // 5. 支付成功逻辑 
    showSuccessToast("支付成功!"); 
    navigateToOrderDetail(); 
  } catch (error) {
    // 捕获所有异步错误并分类处理 
    if (error instanceof NetworkError) { 
      // 网络错误(如 fetchPaymentToken 失败) 
      showErrorToast("网络异常,请检查连接"); 
    } else if (error instanceof PaymentRejectedError) {
      // 支付被拒绝(如用户取消支付) 
      showErrorToast("支付已取消"); 
    } else if (error.name === 'AbortError') {
      // 轮询超时(自定义AbortController触发) 
      showErrorToast("支付状态确认超时,请查看订单");
    } else { 
      // 未知错误兜底处理 
      logErrorToServer(error); 
      // 上报错误日志 
      showErrorToast("支付失败,请联系客服"); 
      }
    } finally {
      // 无论成功与否,关闭加载状态 setLoading(false);
      } 
    }
相关推荐
读心悦1 小时前
CSS:盒子阴影与渐变完全解析:从基础语法到创意应用
前端·css
m0_616188491 小时前
使用vue3-seamless-scroll实现列表自动滚动播放
开发语言·javascript·ecmascript
湛海不过深蓝2 小时前
【ts】defineProps数组的类型声明
前端·javascript·vue.js
layman05282 小时前
vue 中的数据代理
前端·javascript·vue.js
柒七爱吃麻辣烫2 小时前
前端项目打包部署流程j
前端
layman05283 小时前
vue中理解MVVM
前端·javascript·vue.js
一舍予4 小时前
八股文-js篇
开发语言·前端·javascript
鸡鸭扣4 小时前
DRF/Django+Vue项目线上部署:腾讯云+Centos7.6(github的SSH认证)
前端·vue.js·python·django·腾讯云·drf
龙井茶Sky4 小时前
验证码与登录过程逻辑学习总结
前端·登录·验证码