之前一直没有想过到底什么异常会被 try…catch 捕捉到,通过 多点世界 的这篇文章,对这个问题有了清晰的认识,觉得有必要做一个学习记录。
首先,是简单的一句话概括:
能捕捉到的异常,必须是线程执行已经进入 try catch 但 try catch 未执行完的时候抛出来的
文章中举的例子包括几种情况:
- 语法检查阶段的语法异常
- 异步执行中的异常
- Promise
语法异常
例1中属于语法检查阶段的语法异常,报错时不在 try…catch 线程执行过程中,不会被 try…catch 捕捉到:
try{a.}catch(e){console.log("error",e);}// outputUncaught SyntaxError: Unexpected token '}'
例2和例3中函数执行时语法异常,此时已在 try…catch 线程执行过程中,会被捕获:
try{function d(){a.b;}d();}catch(e){console.log("error",e);}// outputerror ReferenceError: a is not defined
function d(){a.b;}try{d();}catch(e){console.log("error",e);}// outputerror ReferenceError: a is not defined
若函数执行在 try…catch 之外,则不会被 try…catch 捕获,例如:
try{function d(){a.b;}}catch(e){console.log("error",e);}console.log(111);d();// output111Uncaught ReferenceError: a is not defined
异步方法中的异常
try{setTimeout(()=>{console.log(a.b);}, 100)}catch(e){console.log('error',e);}console.log(111);//output111Uncaught ReferenceError: a is not defined
setTimeout 中的代码是在 100ms 后执行的,此时 try…catch 代码块已经执行完成, console.log(111) 都已执行,也就是说已经不处于 try…catch 线程中了,所以 setTimeout 中的异常不会被 try…catch 捕获。
Promise 中的异常
try{new Promise(function (resolve, reject) {a.b;}).then(v=>{console.log(v);});console.log(111);}catch(e){console.log('error',e);}console.log(222);// output111222Uncaught (in promise) ReferenceError: a is not defined
这里 try…catch 没有捕捉到异常,是因为 Promise 内部有捕获异常的处理(异常会传到 .catch 中),也就没有抛出到外部的 try…catch。Promise 内部具体实现可以参考一些 Promise polyfill 代码,例如 promise、[core-js]promise。
async/await
那为什么 await 又需要 try…catch 捕捉异常呢?语句执行到 await 时,必须等到 await 后的 Promise 有了返回值,才会执行下一行代码,如果有错误就会抛出。也就是 async 函数执行时,进程依然在 try…catch 内部,所以可以捕捉异常。
