不知道你有沒(méi)有遇到這樣一種情況,某天你寫(xiě)的代碼在線上突然發(fā)生錯(cuò)誤,然后你打開(kāi)控制臺(tái),卻對(duì)著打過(guò)包的錯(cuò)誤信息毫無(wú)頭緒?又或者說(shuō)是代碼在node端出現(xiàn)了問(wèn)題,你查看錯(cuò)誤日志的時(shí)候,卻發(fā)現(xiàn)日志文件中都是雜亂的錯(cuò)誤堆棧信息。
其實(shí)上面這些問(wèn)題都可以通過(guò)在代碼中引入合適的錯(cuò)誤機(jī)制進(jìn)行解決。大部分時(shí)候,由于程序員在開(kāi)發(fā)過(guò)程中更加關(guān)注需求的實(shí)現(xiàn),反而會(huì)忽視一些底層的工作。而錯(cuò)誤處理機(jī)制就相當(dāng)于我們代碼上的最后一道保險(xiǎn),在程序發(fā)生已知或者意外的問(wèn)題的時(shí)候,可以讓開(kāi)發(fā)者在第一時(shí)間獲取信息,從而快速定位并解決問(wèn)題。
常用的錯(cuò)誤處理機(jī)制
首先我們來(lái)了解一下目前前端領(lǐng)域到底有哪些錯(cuò)誤處理機(jī)制。
try catch
try...catch這種錯(cuò)誤處理機(jī)制一定是大家最熟悉的,Javascript語(yǔ)言內(nèi)置的錯(cuò)誤處理機(jī)制可以在檢測(cè)到代碼異常的時(shí)候直接進(jìn)行捕獲并處理。
function test() { try { throw new Error("error"); } catch(err) { console.log("some error happened:"); }} test()
node原生錯(cuò)誤處理機(jī)制
大多數(shù)Node.js核心API都提供的是利用回調(diào)函數(shù)處理錯(cuò)誤,例如:
const fs = require('fs');function read() { fs.readFile("/some/file/does-not-exist", (err, data) => { if(err) { throw new Error("file not exist"); } console.log(data); });}read();
通過(guò)回調(diào)函數(shù)的err參數(shù)來(lái)檢查是否出現(xiàn)錯(cuò)誤,再進(jìn)行處理。之所以Node.js采用這種錯(cuò)誤處理機(jī)制,是因?yàn)楫惒椒椒ㄋa(chǎn)生的方法并不能簡(jiǎn)單地通過(guò)try...catch機(jī)制進(jìn)行攔截。
promise
Promise是用于處理異步調(diào)用的規(guī)范,而其提供的錯(cuò)誤處理機(jī)制,是通過(guò)catch方法進(jìn)行捕獲。
fs.mkdir("./temp").then(() => { fs.writeFile("./temp/foobar.txt", "hello");}).catch(err => { console.log(err)});
async/await + try catch
第三種錯(cuò)誤處理機(jī)制是采用async/await語(yǔ)法糖加上try...catch語(yǔ)句進(jìn)行的。這樣做的好處是異步和同步調(diào)用都能夠使用統(tǒng)一的方式進(jìn)行處理了。
async function one() { await two();}async function two() { await "hello"; throw new Error("error");}async function test() { try { await one(); } catch(error) { console.log(error); }}test();
解決方案
promisify
如果你的代碼中充斥著多種不同的錯(cuò)誤處理模式,那么維護(hù)起來(lái)是十分困難的。而且代碼的可讀性也會(huì)大大降低。因此,這里推薦采用的統(tǒng)一的解決方案。對(duì)于同步代碼來(lái)說(shuō),直接使用try...catch方式進(jìn)行捕獲處理即可,而對(duì)于異步代碼來(lái)說(shuō),建議轉(zhuǎn)換成Promise然后采用async/await + try...catch這種方式進(jìn)行處理。這樣風(fēng)格統(tǒng)一,程序的健壯性也大大加強(qiáng)。例如下面這個(gè)數(shù)據(jù)庫(kù)請(qǐng)求的代碼:
const database = require("database");function promiseGet(query) { return new Promise((resolve, reject) => { database.get(query, (err, result) => { if (err) { reject(err); } else { resolve(result); } }) })}async function main() { await promiseGet("foo");}main();
自定義錯(cuò)誤類型
直接使用系統(tǒng)原生的錯(cuò)誤信息通常會(huì)顯得太過(guò)單薄,不利于后續(xù)進(jìn)一步的分析和處理。所以為了讓代碼的錯(cuò)誤處理機(jī)制的功能更加強(qiáng)大,我們勢(shì)必要多花點(diǎn)精力進(jìn)行額外的改造。
新聞熱點(diǎn)
疑難解答
圖片精選