JavaScript前端常见异常及如何捕获详解

作者:

文章目录
  • js全局异常捕获:window.onEerror 和 window.addEventLisenter('error') Promise全局异常捕获:unhandledrejection 框架级的全局异常捕获 React:React的ErrorBoundary // ErrorBoundary的示例 class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { this.setState({ hasError: true }); // 在这里可以做异常的上报 logErrorToMyService(error, info); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } <ErrorBoundary> <MyWidget /> </ErrorBoundary> Vue:Vue的Vue.config.errorHandler axios: 请求统一底层封装异常处理拦截器 interceptors
  • Vue 用 errorHandler 和 React 用 componentDidCatch
  • 目录
    • 全局捕获-架构侧
    • 全局捕获-框架层
    • 局部捕获-业务侧
      • 可疑代码块try-catch
      • Promise异常
      • 接口请求异常
      • 全局静态资源异常监控

    js全局异常捕获:window.onEerror 和 window.addEventLisenter('error')

    Promise全局异常捕获:unhandledrejection

    框架级的全局异常捕获

    React:ReactErrorBoundary

    // ErrorBoundary的示例
    class ErrorBoundary extends React.Component {
        constructor(props) {
          super(props);
          this.state = { hasError: false };
        }
      
        componentDidCatch(error, info) {
          this.setState({ hasError: true });
          // 在这里可以做异常的上报
          logErrorToMyService(error, info);
        }
      
        render() {
          if (this.state.hasError) {
            return <h1>Something went wrong.</h1>;
          }
          return this.props.children;
      }
      
      <ErrorBoundary>
        <MyWidget />
      </ErrorBoundary>
    

    Vue:VueVue.config.errorHandler

    axios: 请求统一底层封装异常处理拦截器 interceptors

    Vue 用 errorHandler 和 React 用 componentDidCatch

    try catch能捕获捉到运行时非异步错误,无法捕获语法错误和异步错误。这个需要注意。

    合理使用,不要过度使用。有得异常需要抛出去给外部处理。

    常见的需要注意用try-catch包裹,捕获异常的情况

    JSON处理必须使用try catch捕获异常

    try {
      const res=fetch(*)
      JSON.parse(res); // res 为服务端返回的数据
    } catch(e) {
       // 捕获到详细的错误,在这里处理日志上报或其他异常处理等逻辑,如是否提示用户,是否有异常下的兜底数据,比如使用缓存数据等
      console.error("服务端数据格式返回异常,无法解析", res);
      
    }
    
    // 注意:下面的异常try catch无法捕获
    
    try {
      setTimeout(() => {
        undefined.map(v => v);
      }, 1000)
    } catch(e) {
      console.log("捕获到异常:", e);
    }
    

    async await异步请求

    正则表达式处理

    buffer处理

    注意未被捕获的promise异常会作为全局异常抛出。

    局部Promise捕获两种方式:

    // 1. Promise().catch()
    let promise = new Promise((resolve,reject)=>{}).catch(e=>{
       // handle error
    })
    
    // 2. async/await + try/catch
    let promise = new Promise();
    async function test() {
      try {
        await promise;
      } catch (e) {
        // handle error
      }
    }
    

    用Promise().catch(),

    全局Promise异常用window.addEventListener("unhandledrejection")

    注意:

    Promise自己的异常只能被自己catch, 或在try/catch里以await的方式调用来捕获。否则就会作为ERR_UNHANDLED_REJECTION异常抛出到全局。

    外层Promise不能不能捕获内层Promise的异常。

    let p1 = new Promise(async (resolve, reject) => {
      return reject(100); // 被捕获
    });
    async function fn() {
      try {
        let result = await p1;
        console.log(2, result); //这里不会执行
      } catch (e) {
        console.log("e:", e); //这里不会执行
      }
    }
    fn();
    
    let p1 = new Promise(async (resolve, reject) => {
      return reject(100); // 未被捕获,会抛出全局异常:ERR_UNHANDLED_REJECTION
    });
    function fn() {
      try {
        let result = p1;
        console.log(2, result); //这里不会执行
      } catch (e) {
        console.log("e:", e); //这里不会执行
      }
    }
    fn();
    
    let p1 = new Promise(async (resolve, reject) => {
      console.log("after reject");
      return Promise.reject(100); // 未被捕获,会抛出全局异常:ERR_UNHANDLED_REJECTION
    });
    async function fn() {
      try {
        let result = await p1;
        console.log(2, result); //这里不会执行
      } catch (e) {
        console.log("e:", e); //这里不会执行
      }
    }
    fn();
    
    let p1 = new Promise(async (resolve, reject) => {
      return Promise.reject(100); // 未被捕获,会抛出全局异常:ERR_UNHANDLED_REJECTION
    }).catch((e) => {
      console.log("promise out e", e); // 这里不会执行
    });
    async function fn() {
      try {
        let result = await p1;
        console.log(2, result); //这里不会执行
      } catch (e) {
        console.log("e:", e); //这里不会执行
      }
    }
    fn();
    

    Promise里同步抛出的异常,会触发Promise.reject而被捕获。但异步抛出的异常,不会触发Promise.reject,因此不会被捕获。

    new Promise((resolve, reject) => {
      throw new Error("Error1"); // 等效于reject
    }).catch((e) => {
      console.log("异常被捕获到了1");
    });
    
    new Promise(async (resolve, reject) => {
      reject(new Error("Error2"));
    }).catch((e) => {
      console.log("异常被捕获到了2");
    });
    
    new Promise(async () => {
      throw new Error("Error3");
    }).catch((e) => {
      console.log("异常被捕获到了3");
    });
    

    Fetch 用async await + try catch

    Axios 请求,自行处理自定义的异常上报

    window.addEventListener("error") 或者资源标签的onError属性

    到此这篇关于JavaScript前端常见异常及如何捕获详解的文章就介绍到这了,更多相关JavaScript异常捕获内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • JavaScript中的事件与异常捕获详析
    • javascript中的try catch异常捕获机制用法分析
    • JS使用onerror捕获异常示例
    • js异常捕获方法介绍

    站内搜索