詳解JavaScript錯誤捕獲
一、基本使用與邏輯
使用
try{
//code....
}catch(err){
//error handling
}finally{
//no matter what happens in the try/catch (error or no error), this code in the finally statement should run.
}
邏輯

二、特性
try...catch 僅適用于運行時錯誤,解釋階段錯誤無法正常工作
try{
{{{{{{{
}catch(err){
console.error(err)
}
//引擎在‘parse-time'出錯,導(dǎo)致無法理解代碼,因此無法捕捉
try...catch 只能同步工作
try{
setTimeout(function(){
undefinedVariable;
},1000)
}catch(err){
console.error(err)
}
//setTimeout的回調(diào)函數(shù)執(zhí)行時,引擎已經(jīng)離開try...catch結(jié)構(gòu)
finally 能讓try塊中的return語句失效
function test(){
try {
return 1;
} catch(error) {
return 2;
} finally {
return 3;
}
}
console.log(test());
//3
三、錯誤對象
當程序發(fā)生error,js內(nèi)部會生成一個包含error細節(jié)的對象,該對象會被作為參數(shù)傳進catch
對于所有內(nèi)置錯誤,錯誤對象具有兩個主要屬性
- name 錯誤類型
- message 文本類型的錯誤信息
- stack (非標準屬性)發(fā)生錯誤時的調(diào)用棧信息,主要用于調(diào)試
try {
lalala; // error, variable is not defined!
} catch (err) {
alert(err.name); // ReferenceError
alert(err.message); // lalala is not defined
alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)
// Can also show an error as a whole
// The error is converted to string as "name: message"
alert(err); // ReferenceError: lalala is not defined
}
理論上,我們可以throw任何東西作為錯誤對象,但最好的習(xí)慣是throw一個具有name,message的對象,以便和內(nèi)置錯誤對象保持兼容
番外:內(nèi)置的錯誤對象
| 對象 | 含義 |
|---|---|
| ReferenceError | 引用未定義變量時觸發(fā) |
| SyntaxError | 使用不合法的語法結(jié)構(gòu)時觸發(fā) |
| TypeError | 值得類型非預(yù)期時觸發(fā) |
| URIError | 錯誤使用全局URI函數(shù)如encodeURI()、decodeURI()等時觸發(fā) |
| RangeError | 對Array構(gòu)造函數(shù)使用錯誤的長度值,對Number.toExponential()、Number.toFixed()或Number.toPrecision()使用無效數(shù)字等 |
| EvalError | 全局函數(shù)eval()中發(fā)生的錯誤 |
四、較好的catch和throw策略
catch錯誤不單單是為了防止程序掛掉,更重要的目的是方便調(diào)試,找bug,所以對錯誤的處理策略,稍微可以體現(xiàn)出碼者的優(yōu)雅性
俗話說的好,碼者,人恒雅也,盡量遵循一個原則,catch只處理自己知道的錯誤
舉個梨子
let json = '{ "age": 30 }';
try{
let user = JSON.parse(json);
alert( user.name );
} catch (err) {
console.error('JSON Error:'+err);
}
上述例子的catch策略能保證程序正常,因為catch塊能catch內(nèi)部所有的錯誤,無論是JSON.parse出錯還是user.name不存在報錯,都能被catch到,但兩種錯誤都用同一種打印是不利于調(diào)試的,寫成下面這樣會好一點
let json = '{"age":30}'
try{
let user = JSON.parse(json);
alert(user.name)
}catch(err){
if(err instanceof SyntaxError){
console.error('JSON Error:'+err);
}
else throw err;
}
每個catch塊處理自己知道得,可能會出現(xiàn)得錯誤,就是說,編程人員在編程的時候,catch那些預(yù)料到的錯誤,而將可能自己沒料到的錯誤拋到外面。
五、Promise的錯誤處理
眾所周知,Promise是會吞掉error的,因為promise的實現(xiàn)就在內(nèi)部對所有error進行了捕獲,且捕獲到的error不是向外拋出(外指promise之外),而是沿著鏈找到最近的onreject回調(diào)傳入,所以promise的錯誤處理只有兩種辦法
- 設(shè)置onreject回調(diào)
- 全局捕獲
舉個栗子
try{
new Promise((resolve,reject)=>{
throw new Error('promise error')
}).catch(()=>{
//錯誤在最近的onreject回調(diào)被捕獲
console.error(err);
})
}catch(err){
//永遠不會執(zhí)行,promise吞掉error
console.error(err);
}
另外需要注意,無論是執(zhí)行者函數(shù)(executor)和還是 promise 的處理程序(handler),內(nèi)部發(fā)生的錯誤統(tǒng)統(tǒng)吞掉,相當于被隱式catch,error會自動找到最近的onreject回調(diào)傳進去
try{
new Promise((resolve,reject)=>{
resolve();
}).then(()=>{
throw new Error('promise then error');
}).catch((err){
console.error(err);
})
}catch(err){
//地球毀滅之前都不會執(zhí)行
console.error(err)
}
同理,在錯誤找到onreject傳進去之前,經(jīng)過的then注冊的onfulfilled回調(diào)統(tǒng)統(tǒng)失效,直到找到onreject回調(diào),處理之后,onreject回調(diào)之后的onfulfilled回調(diào)才正常
try {
new Promise((resolve, reject) => {
throw new Error('promise error')
}).then((ret) => {
//錯誤沒有處理,失效
console.log('then1:' + ret)
}).catch((err) => {
//錯誤處理了,后序正常
console.error(err);
return 'handled'
}).then((ret) => {
//正常執(zhí)行
console.log('then2' + ret);
})
} catch (err) {
//同樣的,人類毀滅之前都不會執(zhí)行
console.error(err)
}
// Error:promise error
//then2handled
那整條鏈一個catch都沒設(shè)置會怎么樣呢?
那這個error就會擊穿地心,一直穿透到全局,根據(jù)宿主環(huán)境的不同觸發(fā)不同的全局事件,比如說瀏覽器中會觸發(fā) unhandledrejection事件,node環(huán)境中也會觸發(fā)unhandledRejection事件,一般會對這事件進行監(jiān)聽,再顯示信息給編程人員或者用戶
番外1:chromium / v8 / v8 / 3.29.45 的 Promise內(nèi)部錯誤捕捉

番外2:async/await錯誤捕捉
六、性能損耗
After V8 version 6 (shipped with Node 8.3 and latest Chrome), the performance of code inside try-catch is the same as that of normal code. ------ 爆棧網(wǎng)
(稍微測了一下,相差無幾)
以上就是詳解JavaScript錯誤捕獲的詳細內(nèi)容,更多關(guān)于JavaScript 錯誤捕獲的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript基礎(chǔ)篇(6)之函數(shù)表達式閉包
這篇文章主要介紹了javascript基礎(chǔ)篇(6)之函數(shù)表達式閉包的相關(guān)資料,需要的朋友可以參考下2015-12-12
JavaScript之Map和Set_動力節(jié)點Java學(xué)院整理
這篇文章主要為大家詳細介紹了JavaScript之Map和Set的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
在vs2010中調(diào)試javascript代碼方法
只在IE瀏覽器中測試成功了,在谷歌瀏覽中沒有測試成功,其他瀏覽器沒有測試。2011-02-02
javaScript對文字按照拼音排序?qū)崿F(xiàn)代碼
這篇文章主要介紹了javaScript對文字按照拼音排序?qū)崿F(xiàn)代碼,有需要的朋友可以參考一下2013-12-12
drag-and-drop實現(xiàn)圖片瀏覽器預(yù)覽
chrome的drag and drop API,它能將本地的圖片放到瀏覽器中進行預(yù)覽,猜想一下當我們把圖片拖拽到瀏覽器里會發(fā)生什么事情,你的瀏覽器試圖打開一個新的頁面并加載這個圖片。這篇文章給我們介紹drag-and-drop實現(xiàn)圖片瀏覽器預(yù)覽,需要的朋友可以參考下2015-08-08

