一文搞定JS异常捕获

在这里插入图片描述

  关于JS的异常捕获,主要分为两种,一种为同步情况下的异常捕获,一种为一步执行下的异常捕获;异常捕获的【坑】主要集中在异步场景。

同步

  在同步场景下,简单粗暴,直接使用try/catch解决问题。

(function() {
  try {
    // catch: ReferenceError: obj is not defined
    console.log(obj.error)
  } catch (e) {
    console.log('catch:', e)
  }
})();

catch: ReferenceError: obj is not defined
    at <anonymous>:4:17
    at <anonymous>:8:3

异步

setTimeout异常

在异步场景下,按照上面的异常捕获方式是无法捕获到异常的,如下

// 无法捕获到异常
(function() {
  try {
    setTimeout(function() {
      console.log(obj.error)
    }, 500)
  } catch (e) {
    console.log('catch:', e)
  }
})()

Uncaught ReferenceError: obj is not defined
    at <anonymous>:4:19
    at i (init.js:1)

之所以无法捕获到异常,原因在于异步方法执行时,主流程已执行完毕,try/catch已经退出函数调用栈;正确的异常捕获如下:

(function() {
  try {
    setTimeout(function() {
      try {
        console.log(obj.error)
      } catch (e) {
        // 此处捕获到异常
        console.log('catch1:', e)
      }
    }, 500)
  } catch (e) {
    // 此处无法捕获到异常
    console.log('catch2:', e)
  }
})()

catch1: ReferenceError: obj is not defined
    at <anonymous>:5:21
    at i (init.js:1)

从这里可以看出,最外层的try/catch是不生效的,可以去掉。

promise异常

首先通过两端代码来看promise的异常捕获情况
代码一:

(function() {
  try {
    const promise = new Promise((resolve, reject) => {
      setTimeout(function() {
        // 此处的异常无法被捕获
        console.log('1', obj.error)
        resolve(100)
      })
    })
    promise.then(result => {
      console.log('result:', result)
    }).catch(error => {
      // 此处无法捕获到异常
      console.log('catch1:', error)
    })
  } catch (e) {
    // 此处无法捕获到异常
    console.log('catch2:', e)
  }
})();

Uncaught ReferenceError: obj is not defined
    at <anonymous>:6:26
    at i (init.js:1)

代码二:

(function() {
  try {
    const promise = new Promise((resolve, reject) => {
      console.log(obj.error)
      setTimeout(function() {
        resolve(100)
      })
    })
    promise.then(result => {
      console.log('result:', result)
    }).catch(error => {
      // 此处捕获到异常
      console.log('catch1:', error)
    })
  } catch (e) {
    // 此处无法捕获到异常
    console.log('catch2:', e)
  }
})()

catch1: ReferenceError: obj is not defined
    at <anonymous>:4:19
    at new Promise (<anonymous>)
    at <anonymous>:3:21
    at <anonymous>:19:3

总结:

  1. 最外层的try/catch对于promise中的异常捕获完全无效
  2. new Promise()中的异步异常(setTimeout)只能在内部捕获
  3. new Promise()中的同步异常只能通过catch捕获

核心:熟悉EventLoop就知道,每个任务使用独立的函数调用栈;所以,每一个task都需要单独捕获异常;使用promise.catch能够捕获到promise任务的异常。

async/await异常

追寻talk is cheap,show me the code的原则,这里直接上验证代码,让实际结果来说明一切。

function f() {
  return new Promise((resolve, reject) => {
    console.log(obj.error)
    setTimeout(function() {
      // 1.这里的异常只能在setTimeout内部使用try/catch捕获
      // console.log(obj.error)
      resolve(100)
    })
  })
}
async function main() {
  try {
    const result = await f().catch(e => {
      // 2.优先捕获到异常
      console.log('catch1:', e)
    })
    console.log(result)
  } catch (e) {
    // 3.如果没有catch1,这里也能捕获到异常
    console.log('catch2:', e)
  }
}
main()

总结:

  1. new Promise()中的异步异常(setTimeout)只能在内部捕获
  2. 可以使用.catch也可使用try/catch来捕获异常,其中.catch优先级较高

作者公众号:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值