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了?

猜你喜欢

转载自blog.csdn.net/ZhaoBuDaoFangXia/article/details/131920143