node端统一错误处理

起因

在之前的项目中我发现每个控制器大约都是这样写的

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

当然这么写其实没有任何问题,甚至是一个很好的习惯,他保证了错误可以被正常的捕获,另外可以在catch里随便做处理,比如console,错误日志。一切都看起来那么完美

转折

那么假设现在有一个开发就是那么刚,写了几十个控制器,然后都没加try catch,理直气壮的说,这么多重复代码真的不能抽象一下统一处理吗。
好吧且不说抽象统一处理的事,解决问题才是目的。
解决吧,他刚我也刚,每个控制器加上不就是了。。。呵呵哒,边骂边加,我想半天也差不多了。
这样真的好吗,万一现在在catch这需要根据e做一些特殊处理呢或者增加一个功能呢?egg的话有一个统一的errorhandle可以配置。确实把整个错误处理可以完整的抽象出来。

面向切面编程

这里的话要提一个java大大朋友告诉我的spring的解决手段,面向切面编程,具体概念网上解释很多,大约可以理解为,在所有控制器前,或者说控制器和服务之间,这样的话就可以实现很多公共逻辑的抽象。
面向切面编程适合做的事,这个spring的实践实在太多我就不赘述了,错误异常处理,日志,权限,这些在切面上的实践都是很好的。

切面与中间件

其实中间件我认为也属于一个切面,这个切面是在请求上下文中的,但是这个切面无法覆盖所有的要求,特别当你需要控制的功能不是以请求为粒度控制的时候,或者说仅仅需要对服务层的服务添加功能的时候。

实践

这里就以开头的那段代码的简化为例。首先是一个包装函数,用来包装所有的控制器的方法

    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的函数进行单独的日志处理。

egg.js的实践

egg在实践上是不太一致,因为控制器并非简单的实例化,如果需要对egg的控制器的进行包装则需要在loader中进行包装。
参考:https://eggjs.org/zh-cn/advan…
之后会尝试根据现有的业务沉淀出一套egg之上的框架。

    原文作者:求实亭下
    原文地址: https://segmentfault.com/a/1190000014118158
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞