JS异步错误捕获的一些事小结异步错误捕获的一些事小结
引入引入
我们都知道 try catch 无法捕获 setTimeout 异步任务中的错误,那其中的原因是什么。以及异步代码在 js 中是特别常见的,
我们该怎么做才比较?
无法捕获的情况无法捕获的情况
function main() {
try {
setTimeout(() => {
throw new Error('async error')
}, 1000)
} catch(e) {
console.log(e, 'err')
console.log('continue...')
}
}
main();
这段代码中,setTimeout 的回调函数抛出一个错误,并不会在 catch 中捕获,会导致程序直接报错崩掉。
所以说在 js 中 try catch 并不是说写上一个就可以高枕无忧了。难道每个函数都要写吗,
那什么情况下 try catch 无法捕获 error 呢?
异步任务异步任务
宏任务的回调函数中的错误无法捕获
上面的栗子稍微改一下,主任务中写一段 try catch,然后调用异步任务 task,task 会在一秒之后抛出一个错误。
// 异步任务
const task = () => {
setTimeout(() => {
throw new Error('async error')
}, 1000)
}
// 主任务
function main() {
try {
task();
} catch(e) {
console.log(e, 'err')
console.log('continue...')
}
}
这种情况下 main 是无法 catch error 的,这跟浏览器的执行机制有关。异步任务由 eventloop 加入任务队列,并取出入栈(js
主进程)执行,而当 task 取出执行的时候, main 的栈已经退出了,也就是上下文环境已经改变,所以 main 无法捕获 task 的
错误。
事件回调,请求回调同属 tasks,所以道理是一样的。eventloop 复习可以看这篇文章
微任务(promise)的回调
// 返回一个 promise 对象
const promiseFetch = () =>
new Promise((reslove) => {
reslove();
})
function main() {
try {
// 回调函数里抛出错误
promiseFetch().then(() => {
throw new Error('err')
})
} catch(e) {
console.log(e, 'eeee');
console.log('continue');