JavaScript代碼不能被阻斷的穩(wěn)定性建設(shè)
背景
穩(wěn)定性建設(shè)之JavaScript代碼不能被阻斷
js代碼可能會(huì)因?yàn)槟承┰颍瑢?dǎo)致出錯(cuò),進(jìn)而整個(gè)后續(xù)代碼有可能都被阻斷。直接影響線上的穩(wě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
這一行開始報(bào)錯(cuò),后續(xù)的js代碼被阻斷了,console.log(222)
打印不出來
解決辦法
- 解決辦法也很簡(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. 沒考慮到錯(cuò)誤上報(bào)
- 上面的demo沒有考慮錯(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)開一篇文章,就有人在誤人子弟,教別人用 throw, throw這個(gè)東西是不能亂用的,因?yàn)樗麜?huì)阻斷代碼,重要的事情說三遍,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也不是一無是處,但是,他只能在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ò)誤沒有被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ò)誤沒有被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)文章
微信小程序?qū)崿F(xiàn)錨點(diǎn)定位樓層跳躍的實(shí)例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)錨點(diǎn)定位樓層跳躍的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05微信小程序 支付功能開發(fā)錯(cuò)誤總結(jié)
這篇文章主要介紹了微信小程序 支付功能開發(fā)錯(cuò)誤總結(jié)的相關(guān)資料,需要的朋友可以參考下2017-02-02超越Node.js的JavaScript運(yùn)行環(huán)境Bun.js功能特性詳解
這篇文章主要為大家介紹了超越Node.js的JavaScript運(yùn)行環(huán)境Bun.js功能特性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09微信小程序 input輸入框詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了微信小程序 input輸入框詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-01-01前端對(duì)接WebSocket與心跳重連實(shí)現(xiàn)
這篇文章主要為大家介紹了前端對(duì)接WebSocket與心跳重連實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07