寫代碼時經(jīng)常會用到
try catch,防止一些JS報錯,導(dǎo)致頁面掛掉。那么到底哪些JS異常能被捕獲到呢?
簡單解釋就是:在報錯的時候,線程執(zhí)行已經(jīng)進入
try catch代碼塊,并且處在try catch里,才能被捕捉到。(之前,之后都無法捕捉異常)
-
下面三個小栗子,解釋一下
try catch的前中后
?? 例子1:
try{
a(
} catch (e) {
console.log('error', e)
}
// output
Uncaught SyntaxError: Unexpected token }
例子1 語法異常(SyntaxError),因為語法異常是在語法階段就報錯了,所以線程還沒進入 try catch 代碼塊,就捕獲不到異常。
?? 例子2:
function d () {a.b}
try {
d()
} catch (e) {
console.log('error', e)
}
// output
error ReferenceError: a is not defined
例子2 報錯的時機,是代碼執(zhí)行進入了 try catch ,執(zhí)行 d 方法的時候,線程執(zhí)行處在 try 里面,所以能捕捉到。
?? 例子3:
try {
function d () {a.b}
} catch (e) {
console.log('error', e)
}
d()
// output
error ReferenceError: a is not defined
例子3 方法定義在 try catch 代碼塊里,但是執(zhí)行方法在 try catch 外,執(zhí)行 d 方法的時候報錯,此時 try catch 已經(jīng)執(zhí)行完成,所以無法捕捉異常。
三個例子之后應(yīng)該能理解怎樣的JS異常可以被捕獲了,但是在我們用 promise 的時候發(fā)現(xiàn)相對于外部的 try catch ,Promise 沒有異常!
promise & try catch
?? 例子4:
try{
new Promise((resolve, reject) => {
a.b
}).then(v => {
console(v)
})
} catch (e) {
console.log('error', e)
}
// output
Uncaught (in promise) ReferenceError: a is not defined
例子4 線程在執(zhí)行a.b的時候,適時向?qū)儆谕綀?zhí)行,try catch 并未執(zhí)行完成,為什么捕獲不到異常呢?
事實上,Promise 的異常都是由 reject 和 Promise.prototype.catch 來捕獲,不管是同步還是異步。
核心原因是因為 Promise 在執(zhí)行回調(diào)中都用 try catch 包裹起來了,其中所有的異常都被內(nèi)部捕獲到了,并未往上拋異常,所以異常都不會被外層的 try catch 捕捉。
?? 例子5:
function a(){
return new Promise((resolve, reject) =>{
setTimeout(() => {
reject('報錯了')
})
})
}
async function foo () {
try{
await a()
} catch (e) {
console.log('error', e)
}
}
foo()
// output
error 報錯了
為什么 例子5 的異常能被 catch 捕獲到呢,因為報錯的時候,線程執(zhí)行已經(jīng)進入了 try catch 代碼塊,并且異常由 reject 拋出,自然可以捕獲到。
總結(jié):
1. 在報錯的時候,線程執(zhí)行已經(jīng)進入
try catch代碼塊,并且處在try catch里,才能被捕捉到。
2. 不要用
try catch包裹Promise,我們只需要給Promise增加 Promise#catch 就 OK 了