node端統一錯誤處理

原由

在以前的項目中我發現每一個控制器大約都是這樣寫的html

async function findId (id) {
    let res;
    try{
        res = await document.findById(id);
    }catch(e){
        return false;
    }
}

固然這麼寫其實沒有任何問題,甚至是一個很好的習慣,他保證了錯誤能夠被正常的捕獲,另外能夠在catch裏隨便作處理,好比console,錯誤日誌。一切都看起來那麼完美java

轉折

那麼假設如今有一個開發就是那麼剛,寫了幾十個控制器,而後都沒加try catch,義正詞嚴的說,這麼多重複代碼真的不能抽象一下統一處理嗎。
好吧且不說抽象統一處理的事,解決問題纔是目的。
解決吧,他剛我也剛,每一個控制器加上不就是了。。。呵呵噠,邊罵邊加,我想半天也差很少了。
這樣真的好嗎,萬一如今在catch這須要根據e作一些特殊處理呢或者增長一個功能呢?egg的話有一個統一的errorhandle能夠配置。確實把整個錯誤處理能夠完整的抽象出來。spring

面向切面編程

這裏的話要提一個java大大朋友告訴個人spring的解決手段,面向切面編程,具體概念網上解釋不少,大約能夠理解爲,在全部控制器前,或者說控制器和服務之間,這樣的話就能夠實現不少公共邏輯的抽象。
面向切面編程適合作的事,這個spring的實踐實在太多我就不贅述了,錯誤異常處理,日誌,權限,這些在切面上的實踐都是很好的。編程

切面與中間件

其實中間件我認爲也屬於一個切面,這個切面是在請求上下文中的,可是這個切面沒法覆蓋全部的要求,特別當你須要控制的功能不是以請求爲粒度控制的時候,或者說僅僅須要對服務層的服務添加功能的時候。app

實踐

這裏就以開頭的那段代碼的簡化爲例。首先是一個包裝函數,用來包裝全部的控制器的方法框架

function controllerWrap(controllerFn, self) {
        return async function() {
            let that = self;
            try {
                await controllerFn.apply(that, arguments);
            } catch(e) {
                throw(e);
            }
        };
    }

其實注意點也就兩個,注意上下文,而後是保證controllerFn的arguments不要丟了,其實也就是ctx和next的
在把全部的控制器實例化後(通常在都會把控制器造成單例模式,以後只要遍歷這些單例中的方法包裹控制器函數就能夠了)。固然能夠在wrap中注入更多統一處理函數,也能夠經過函數名作一些判斷,好比對全部名字中包含save的函數進行單獨的日誌處理。async

egg.js的實踐

egg在實踐上是不太一致,由於控制器並不是簡單的實例化,若是須要對egg的控制器的進行包裝則須要在loader中進行包裝。
參考:https://eggjs.org/zh-cn/advan...
以後會嘗試根據現有的業務沉澱出一套egg之上的框架。函數

相關文章
相關標籤/搜索