JavaScript代碼不能被阻斷的穩(wěn)定性建設
背景
穩(wěn)定性建設之JavaScript代碼不能被阻斷
js代碼可能會因為某些原因,導致出錯,進而整個后續(xù)代碼有可能都被阻斷。直接影響線上的穩(wěn)定性
最常見的js被阻斷的情況
console.log(111)
// 預期 a = {}
// 結果
a = undefined
a.a = 1
console.log(222) // js代碼不能執(zhí)行到這一行
這個代碼很明顯會報錯,在a.a = 1這一行開始報錯,后續(xù)的js代碼被阻斷了,console.log(222)打印不出來
解決辦法
- 解決辦法也很簡單,用 try...catch... 捕獲住錯誤就好了
console.log(111)
try {
// 預期 a = {}
// 結果
a = undefined
a.a = 1
} catch (e) {
console.error(e)
}
console.log(222) // js代碼可以執(zhí)行到這一行
容易被我們忽視的點
1. 沒考慮到錯誤上報
- 上面的demo沒有考慮錯誤上報,發(fā)生錯誤時,外部根本捕獲不到(即使你接入了sentry類的產(chǎn)品),因為error被try catch給吃掉了
try {
// 預期 a = {}
// 結果
a = undefined
a.a = 1
} catch (e) {
console.error(e)
// 公司內(nèi)部的上報函數(shù)
someReportFunction('sendEvent', {
name: 'try_catch_error',
params: {
errorMsg: e.message,
errorStack: e.stack
},
});
}
2. 錯用throw
隨便點開一篇文章,就有人在誤人子弟,教別人用 throw, throw這個東西是不能亂用的,因為他會阻斷代碼,重要的事情說三遍,throw會阻斷代碼,throw會阻斷代碼,throw會阻斷代碼

例如:
console.log(111)
try {
// 預期 a = {}
// 結果
a = undefined
a.a = 1
} catch (e) {
console.error(e)
throw e // throw會阻斷代碼,導致下面不執(zhí)行
}
console.log(222) // 不能執(zhí)行到這一行
當然throw也不是一無是處,但是,他只能在try{ 里面使用 },不能在try之外的地方使用throw,包括catch
console.log(111)
try {
throw new Error(111)
} catch (e) {
console.error(e)
}
console.log(222)
function getData () {
if (...) {
...
} else {
throw new Error(111)
}
}
console.log(111)
try {
getData()
} catch (e) {
console.error(e)
}
console.log(222)
3. 異步代碼catch不到,還是會被阻斷
console.log(111111111)
try {
setTimeout(() => {
a = undefined
a.a = 1 // 代碼被阻斷于此
console.log('error') // 不能執(zhí)行到這一行
}, 0)
} catch (e) {
console.error(e) // 異步代碼catch不到
}
console.log(222222222)
setTimeout(() => {
console.log('setTimeout') // 瀏覽器可以執(zhí)行到這一行,node的不行(node14和16版本都test了)
}, 2000)
4. import()和require()的錯誤捕獲表現(xiàn)不一致
// a.js
console.log(111111111)
try {
require('./b.js')
} catch (e) {
console.log('error') // 錯誤會被正常catch到
console.error(e)
}
console.log(222222222)
setTimeout(() => {
console.log('setTimeout')
}, 2000)
// b.js
console.log(1)
a = undefined
a.a = 1
console.log(2)
// 結果打印 (require被正常捕獲)
111111111
1
error
TypeError: Cannot set property 'a' of undefined
...
...
222222222
setTimeout
- 同樣的代碼換成,import()
// a.js
console.log(111111111)
try {
import('./b.js')
} catch (e) {
console.log('error') // 錯誤沒有被catch到
console.error(e)
}
console.log(222222222)
setTimeout(() => {
console.log('setTimeout')
}, 2000)
// b.js
console.log(1)
a = undefined
a.a = 1
console.log(2)
// 結果打印 (import的 錯誤沒有被catch到)
111111111
222222222
1
(node:92673) UnhandledPromiseRejectionWarning: TypeError: Cannot set property 'a' of undefined
...
setTimeout
正確捕獲import()的方式:其實import()是一個promise,用promise的方法去catch就好了
import('./b.js')
.catch(e => {
console.log('error')
console.error(e)
})
結論:
- try catch 不能捕獲import()模塊的錯誤,require可以被捕獲
- import() 用promise的方法去catch就好了
背景:
- require是運行時加載(可以理解為,函數(shù)調用)
- import()是動態(tài)import,會延遲加載,是異步任務(微任務),是promise
以上就是JavaScript代碼不能被阻斷的穩(wěn)定性建設的詳細內(nèi)容,更多關于JavaScript穩(wěn)定建設的資料請關注腳本之家其它相關文章!
相關文章
Canvas如何判斷點在形狀內(nèi)及內(nèi)置API性能詳解
這篇文章主要為大家介紹了Canvas如何判斷點在形狀內(nèi)及內(nèi)置API性能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03
關于JavaScript防抖與節(jié)流的區(qū)別與實現(xiàn)
這篇文章主要介紹關于JavaScript防抖與節(jié)流的區(qū)別與實現(xiàn),防抖就是用戶多次觸發(fā)事件,在用戶一直觸發(fā)事件中,事件不會執(zhí)行,只有在用戶停止觸發(fā)事件一段時間之后再執(zhí)行這個事件一次,二節(jié)流是用戶多次觸發(fā)事件,具體詳情一i起來學習下面文章內(nèi)容吧2021-10-10

