異常處理
異常處理可以使程序在流程上更加完善。
在 JavaScript 中可以使用 throw
拋出異常,使用 try ... catch
捕獲錯(cuò)誤。
1. throw
throw 語(yǔ)句用來(lái)拋出一個(gè)用戶自定義的異常。(MDN)
throw 用于拋出一個(gè)異常,這種異常通常是程序出現(xiàn)了不符合預(yù)期的錯(cuò)誤。
alert('出錯(cuò)前');
throw '發(fā)生了一個(gè)錯(cuò)誤!';
alert('出錯(cuò)后');
當(dāng)出現(xiàn) throw
時(shí),程序?qū)?huì)中斷執(zhí)行。
如果 throw
發(fā)生在 try ... catch
中,則會(huì)執(zhí)行 catch
中的代碼塊,同時(shí)將異常信息帶給 catch。
2. try … catch
try…catch 語(yǔ)句標(biāo)記要嘗試的語(yǔ)句塊,并指定一個(gè)出現(xiàn)異常時(shí)拋出的響應(yīng)。
try ... catch
可以用于捕獲異常,當(dāng)出現(xiàn) throw 時(shí),會(huì)結(jié)束 try
內(nèi)的代碼執(zhí)行,直接進(jìn)入到 catch
,執(zhí)行 catch
內(nèi)的代碼塊。
try {
alert('出錯(cuò)前');
throw '發(fā)生了一個(gè)錯(cuò)誤!';
alert('出錯(cuò)后');
} catch (e) { // e 是錯(cuò)誤信息,名字隨意,符合變量命名規(guī)范就行
alert('出錯(cuò)了!錯(cuò)誤是:' + e);
}
需要注意的是,以前 catch 后面的錯(cuò)誤參數(shù)是必須接收的,否則會(huì)報(bào)錯(cuò)。
但 ES2019 中有一個(gè)提案,可以選擇性的提供給 catch 參數(shù),所以最新的 chrome 不傳遞錯(cuò)誤參數(shù)也是可以的。
try {
alert('出錯(cuò)前');
throw '發(fā)生了一個(gè)錯(cuò)誤!';
alert('出錯(cuò)后');
} catch {
alert('出錯(cuò)了!');
}
由于是比較新的提案,所以建議沒(méi)有工具參與代碼編譯時(shí),還是寫(xiě)上錯(cuò)誤參數(shù)的接收,避免因?yàn)g覽器兼容性造成的問(wèn)題。
在 try 后面還可以跟 finally
部分,即無(wú)論 try 中的代碼塊是否拋出錯(cuò)誤,都會(huì)執(zhí)行 finally
代碼塊。
try {
alert('開(kāi)始請(qǐng)求數(shù)據(jù),loading 顯示');
throw '沒(méi)有網(wǎng)絡(luò)';
alert('請(qǐng)求結(jié)果是:..編不下去了,反正到不了這里');
} catch (e) {
alert('出現(xiàn)錯(cuò)誤:' + e);
} finally {
alert('關(guān)閉 loading');
}
3. 可以寫(xiě)條件的 catch 語(yǔ)句
部分文獻(xiàn)記載了如下格式的 try … catch 語(yǔ)法。
try {
throw 'error';
} catch (e if e instanceof TypeError) {
console.log('TypeError');
} catch (e if e instanceof ReferenceError) {
console.log('ReferenceError');
} catch (e) {
console.log(e);
}
但目前主流瀏覽器基本都無(wú)法正常運(yùn)行這種語(yǔ)法的 try … catch 語(yǔ)句,所以不要使用。
如果有類(lèi)似的需求,可以使用 if 來(lái)代替。
try {
throw 'error';
} catch (e) {
if (e instanceof TypeError) {
console.log('TypeError');
} else if (e instanceof ReferenceError) {
console.log('ReferenceError');
} else {
console.log(e);
}
}
4. Error 對(duì)象
通過(guò) Error 的構(gòu)造器可以創(chuàng)建一個(gè)錯(cuò)誤對(duì)象。當(dāng)運(yùn)行時(shí)錯(cuò)誤產(chǎn)生時(shí),Error的實(shí)例對(duì)象會(huì)被拋出。Error 對(duì)象也可用于用戶自定義的異常的基礎(chǔ)對(duì)象。(MDN)
通常在使用 throw 拋出異常時(shí),會(huì)拋出一個(gè) Error
對(duì)象的實(shí)例。
try {
throw new Error('主動(dòng)拋出一個(gè)錯(cuò)誤');
} catch (e) {
console.error(e);
}
和大部分內(nèi)置對(duì)象一樣,Error 實(shí)例也可以不使用 new
關(guān)鍵字創(chuàng)建。
try {
throw Error('主動(dòng)拋出一個(gè)錯(cuò)誤');
} catch (e) {
console.error(e);
}
拋出 Error 實(shí)例,可以得到出現(xiàn)異常的文件和對(duì)應(yīng)的行號(hào)。
除了 Error
,還有幾種預(yù)定義好語(yǔ)義的異常對(duì)象。
5. 其他異常對(duì)象
URIError
表示以一種錯(cuò)誤的方式使用全局URI處理函數(shù)而產(chǎn)生的錯(cuò)誤;TypeError
值的類(lèi)型非預(yù)期類(lèi)型時(shí)發(fā)生的錯(cuò)誤;SyntaxError
嘗試解析語(yǔ)法上不合法的代碼的錯(cuò)誤;ReferenceError
當(dāng)一個(gè)不存在的變量被引用時(shí)發(fā)生的錯(cuò)誤;RangeError
當(dāng)一個(gè)值不在其所允許的范圍或者集合中拋出的異常;InternalError
表示出現(xiàn)在 JavaScript 引擎內(nèi)部的錯(cuò)誤。非標(biāo)準(zhǔn)對(duì)象,不建議使用;EvalError
本對(duì)象代表了一個(gè)關(guān)于 eval 函數(shù)的錯(cuò)誤.此異常不再會(huì)被 JavaScript 拋出,但是EvalError對(duì)象仍然保持兼容性。
這些異常對(duì)象的使用和 Error
幾乎一致。
瀏覽器碰到對(duì)應(yīng)的異常,也會(huì)拋出。
try {
console.log(notDefinedVariable);
} catch (e) {
console.error(e);
}
因?yàn)?notDefinedVariable
并沒(méi)有定義,所以瀏覽器會(huì)拋出 ReferenceError
異常,同時(shí)提示變量沒(méi)有定義。
6. 小結(jié)
完整的產(chǎn)品業(yè)務(wù)邏輯流程,基本都要 try ... catch
參與控制,因?yàn)槌霈F(xiàn)異常時(shí),還要有對(duì)應(yīng)的動(dòng)作,如網(wǎng)絡(luò)請(qǐng)求異常,則提示用戶重試,或主動(dòng)進(jìn)行超時(shí)重新請(qǐng)求操作。