try catch不能捕获promise的错误

参考链接
try catch不是万能的,不能捕获promise的错误。但可以promise接catch来捕获错误,如果有多层的promise,每层都要加catch。
代码示例

// 捕获失败
try {
    new Promise((resolve,reject)=>{
        throw Error(1)
    })
} catch (e) {
    console.error('catch error')
}

// 能捕获
try {
    new Promise((resolve,reject)=>{
        throw Error(1)
    }).catch(e=>{
        console.error('error catch!')
    })
} catch (e) {
    console.error('catch error', e)
}

// 多层 不能
try {
    new Promise((resolve,reject)=>{
        return new Promise(()=>{
            throw new Error(1)
        })
    }).catch(e=>{
        console.error('error catch!')
    }
    )
} catch (e) {
    console.error('catch error', e)
}

// 每层都catch,然后reject外抛,能捕获
try {
    new Promise((resolve,reject)=>{
        return new Promise(()=>{
            throw new Error(1)
        }).catch(e=>{
            return reject(e)
        })
    }).catch(e=>{
        console.error('error catch!')
    }
    )
} catch (e) {
    console.error('catch error', e)
}

这里的原理是啥?
参考这里,promise的executor里(就是这里)默认有个try catch,当有异常时就会执行reject并把异常作为参数。

我们知道try catch能捕获try代码块的异常,但如果异常在promise里抛出,那异常不是立即执行的,而是调用了reject,而reject是加到microtask里执行的,详细可以了解下javascript的event loop机制
比如如下代码

console.log(1)
new Promise((resolve) => {
  console.log(2)
  throw Error(4)
}).then((e) => { console.log(e) })
console.log(3)

会输出1、2、3后,再抛出异常4。到异常4的时候,已经不在try catch的marcotask了,try catch里的部份已经执行完了,而是在microtask里处理这个异常,所以捕获不了

console.log(1)
new Promise((resolve) => {
  console.log(2)
  throw Error(4)
}).catch(e=>{console.warn(e)})
console.log(3)

所以这样能捕获

这样也可以

new Promise(r=>{

    try{eee} catch(e){console.warn(e)}
})
// ReferenceError: eee is not defined

但这样不行,同理setTimeout异步执行的,try里面的代码实际已经跑完了

try {
    setTimeout(()=>{eee})
}catch(e) {

    console.warn(e)
}

还有一种方法也能捕获,加上await

async function getSomeValue() {
    throw new Error('uh oh');
}

async function a() {
  try {
    const someValue = await getSomeValue();
  } catch (error) {
    console.warn(error);
  }
}

await是等待promise resolve或reject后才继续执行之后的代码,那为啥在外面加try catch就能捕获到?是因为执行又回到macrotask了?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用try catch无法捕获setTimeout的异常是因为setTimeout是一个异步操作,它会将回调函数放入事件队列中,等到主线程任务执行完毕后再执行。因此,try catch无法捕获到setTimeout中的异常。 为了解决这个问题,可以使用Promise来包装setTimeout操作。通过将setTimeout操作封装在一个Promise对象中,并在Promise对象中抛出异常,就可以使用try catch捕获异常了。具体步骤如下: 1. 创建一个Promise对象,将setTimeout操作放在Promise的回调函数中。 2. 在回调函数中,使用try catch捕获可能发生的异常。 3. 如果发生异常,使用reject方法将异常信息传递出来。 4. 如果没有异常,使用resolve方法将操作结果传递出来。 5. 在调用setTimeout的地方,使用await关键字来等待Promise的结果。 这样,即使在setTimeout中发生异常,也可以通过try catch将异常捕获到。代码示例如下: ```javascript function delay(ms) { return new Promise((resolve, reject) => { setTimeout(() => { try { // 这里放置可能发生异常的代码 // 如果发生异常,使用throw语句抛出异常 // 如果没有异常,使用resolve方法传递操作结果 resolve(); } catch (error) { // 如果发生异常,使用reject方法将异常信息传递出来 reject(error); } }, ms); }); } async function example() { try { await delay(1000); // 使用await等待Promise的结果 console.log("setTimeout操作执行成功"); } catch (error) { console.log("捕获到异常:" + error); } } example(); ``` 通过将setTimeout操作封装在Promise中,并在Promise中使用try catch捕获异常,就可以实现对setTimeout的异常进行捕获和处理了。这样就避免了无法使用try catch捕获setTimeout的问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值