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

例如:
console.log(111)
try {
// 預(yù)期 a = {}
// 結(jié)果
a = undefined
a.a = 1
} catch (e) {
console.error(e)
throw e // throw會(huì)阻斷代碼,導(dǎo)致下面不執(zhí)行
}
console.log(222) // 不能執(zhí)行到這一行
當(dāng)然throw也不是一無(wú)是處,但是,他只能在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不到,還是會(huì)被阻斷
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()的錯(cuò)誤捕獲表現(xiàn)不一致
// a.js
console.log(111111111)
try {
require('./b.js')
} catch (e) {
console.log('error') // 錯(cuò)誤會(huì)被正常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)
// 結(jié)果打印 (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') // 錯(cuò)誤沒(méi)有被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)
// 結(jié)果打印 (import的 錯(cuò)誤沒(méi)有被catch到)
111111111
222222222
1
(node:92673) UnhandledPromiseRejectionWarning: TypeError: Cannot set property 'a' of undefined
...
setTimeout
正確捕獲import()的方式:其實(shí)import()是一個(gè)promise,用promise的方法去catch就好了
import('./b.js')
.catch(e => {
console.log('error')
console.error(e)
})
結(jié)論:
- try catch 不能捕獲import()模塊的錯(cuò)誤,require可以被捕獲
- import() 用promise的方法去catch就好了
背景:
- require是運(yùn)行時(shí)加載(可以理解為,函數(shù)調(diào)用)
- import()是動(dòng)態(tài)import,會(huì)延遲加載,是異步任務(wù)(微任務(wù)),是promise
以上就是JavaScript代碼不能被阻斷的穩(wěn)定性建設(shè)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript穩(wěn)定建設(shè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序 天氣預(yù)報(bào)開(kāi)發(fā)實(shí)例代碼源碼
這篇文章主要介紹了微信小程序 天氣預(yù)報(bào)開(kāi)發(fā)實(shí)例代碼源碼的相關(guān)資料,這里含有源碼,需要的朋友可以參考下2017-01-01
TypeScript獲取二叉樹(shù)的鏡像實(shí)例
這篇文章主要為大家介紹了TypeScript獲取二叉樹(shù)的鏡像實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Canvas如何判斷點(diǎn)在形狀內(nèi)及內(nèi)置API性能詳解
這篇文章主要為大家介紹了Canvas如何判斷點(diǎn)在形狀內(nèi)及內(nèi)置API性能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
async-validator實(shí)現(xiàn)原理源碼解析
這篇文章主要為大家介紹了async-validator實(shí)現(xiàn)原理源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
用javascript制作qq注冊(cè)動(dòng)態(tài)頁(yè)面
這篇文章主要介紹了用javascript制作qq注冊(cè)動(dòng)態(tài)頁(yè)面,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-04-04
關(guān)于JavaScript防抖與節(jié)流的區(qū)別與實(shí)現(xiàn)
這篇文章主要介紹關(guān)于JavaScript防抖與節(jié)流的區(qū)別與實(shí)現(xiàn),防抖就是用戶多次觸發(fā)事件,在用戶一直觸發(fā)事件中,事件不會(huì)執(zhí)行,只有在用戶停止觸發(fā)事件一段時(shí)間之后再執(zhí)行這個(gè)事件一次,二節(jié)流是用戶多次觸發(fā)事件,具體詳情一i起來(lái)學(xué)習(xí)下面文章內(nèi)容吧2021-10-10

