JS

梗概

  • 一般而言,抛出未被捕获的异常时,会立即停止当前函数
  • 异常会沿着调用栈一路传递到上层
  • 当调用的函数内部发生了异常传递出来时,就相当于这个函数调用是个异常抛出语句throw
    • 所以也会立即停止执行当前函数

回调函数对异常传递的影响

梗概

  • 一般情况下,执行环境都不会进行特殊跳转,异步函数对异常传递没有影响
  • 特殊情况下(如在setimeout()中抛出的异常),跳转到了一些特殊的执行环境 ^3eac15
    • 用throw 抛出的异常一定不会按预想中的那样传递
    • reject抛出的异常,那就可以按预想中那样传递
      • 虽然传递符合预期,但捕获代码需要特别注意要与异常抛出保持同步
      • 只要捕获块中的代码早在异常抛出前就执行完毕的话,就不会被捕获
  • child::try-catch与.catch的区别

实例:

一般情况下

async function asyncthrow(data?: any) {
    throw new Error("error!!!");
}
function promiseThrow(data?: any) {
    return new Promise((resolve, reject) => {
        throw new Error("error!!!");
    });
}
function promiseReject(data?: any) {
    return new Promise((resolve, reject) => {
        reject(new Error('error!!!'))
    });
}
async function asyncF1(data?: any) {
    await promiseThrow(data)
}
function promiseF1(data?: any) {
    return promiseReject(data)
}
(async function main() {
    try {
        /* 以下两个都能被捕获到 */
        await asyncF1()
        await promiseF1()
    } catch (error) {
        console.log(error)
    }
})()

特殊情况下

function promiseThrow() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            throw new Error("!!!");
        }, 2000)
    })
}
function promiseReject() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error("!!!"));
        }, 2000)
    })
}
async function throwShell() {
    await promiseThrow()
}
async function rejectAsyncShell() {
    await promiseReject()
}
function rejectShell() {
    return promiseReject()
}
(async function main() {
    try {
        await throwShell() //捕捉不到
        await rejectAsyncShell() //捕获成功
        rejectAsyncShell() //捕获不到
        await rejectShell()//捕获成功
    } catch (error) {
        console.log('catch!!!\n', error)
    }
    throwShell().catch((error) => { console.log('catch!!!\n', error) })//捕捉不到
    rejectAsyncShell().catch((error) => { console.log('catch!!!\n', error) })//捕获成功
    rejectShell().catch((error) => { console.log('catch!!!\n', error) })//捕获成功
})()
// 不管是否捕获得到, 最终error的信息都是一样的:
// throw new Error("!!!");
// ^
// Error: !!!
// at Timeout._onTimeout (d:\3000file\3700project\Code\TypeScript\scr\index.ts:4:19)
// at listOnTimeout (node:internal/timers:559:17)
// at processTimers (node:internal/timers:502:7)