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)