欢迎继续关注NestJs学习之旅系列文章,关注公众号获取最新教程!传统的异常处理在前面的内容中,我们介绍了NestJs常用的几个组件,但是有一点没有说明。当我们的应用程序需要中断请求并输出错误信息时,我们需要做什么呢?这个问题有两种解决方法:services层直接返回中断请求的响应对象,controller可以直接输出该对象if(!this.allowLogin()){return{errcode:403,errmsg:'Loginnot允许'};}服务层抛出异常,控制器捕获异常,然后输出响应对象。以上两种方式都有一定的缺点:控制器调用多个服务时,需要根据服务层的返回值进行错误判断。如果判断失误,将导致原本需要中断的请求处理继续运行,造成不可预知的后果。如果每个controller都需要try/catchservices层抛出的异常,就会有很多“重复”的代码。有没有类似SpringBoot的ExceptionHandler?类似的解决方案呢?NestJs异常处理NestJs提供了统一的异常处理程序来集中处理运行过程中未捕获的异常,并且可以自定义响应参数,非常灵活。默认响应NestJs内置了一个默认的全局异常过滤器,用于处理HttpException(及其子类)的异常。如果抛出的异常不是上述异常,将响应如下默认JSON:{"statusCode":500,"message":"Intervalservererror"}内置异常过滤器由于NestJs有内置的默认异常过滤器,如果里面抛出的应用程序HttpException可以被NestJs自动捕获。例如在services层抛出HttpException:@Injectable()exportclassUserService{login(username:string,password:string){if(!this.allowLogin()){thrownewHttpException('Youarenotauthorized登录',HttpStatus.FORBIDDEN);}return{user_id:1,token:'faketoken'}}}控制器可以正常调用服务:@Controller('users')exportclassUserController{constructor(privatereadonlyuserService:UserService){}@Post('login')login(@Body('username')username:string,@Body('password')password:string){returnthis.userService.login(username,password);}}客户端访问/user/login时,如果不允许登录,会收到如下响应:{"statusCode":403,"message":"Youarenotauthorizedtologin"}一般情况下,信息上面的json返回的还不够,比如有些业务没有地方自定义自定义错误码。如果你有这种需求,可以将对象传递给HttpException的第一个参数:thrownewHttpException({errcode:40010,errmsg:'Youarenotauthorizedtologin'},HttpStatus.FORBIDDEN);客户端访问时,如果不允许登录,会收到如下响应:{"errcode":40010,"errmsg":"Youarenotauthorizedtologin"}企业级应用开发过程中的自定义异常,使用HttpException进行处理对开发不友好。一种常用的方法是自定义一个UserException来携带业务异常(系统运行正常,但是当前请求不满足业务要求而中断。比如注册时用户名重复,回调,并且此时数据库查询正常,没错,这就是业务异常和系统异常的区别)。exportclassUserExceptionextendsHttpException{constructor(errcode:number,errmsg:string,statusCode:number){super({errcode,errmsg},statusCode);}}业务层在使用该异常时可以直接使用如下代码,将原来传递对象的代码扁平化:thrownewUserException(40010,'Youarenotauthorizedtologin',HttpStatus.FORBIDDEN);语义业务异常使用自定义异常时,HTTP协议层正常,抛出403错误有点不符合语义需求。修改上面的例子:exportclassUserExceptionextendsHttpException{constructor(errcode:number,errmsg:string){super({errcode,errmsg},HttpStatus.OK);}}thrownewUserException(40010,'您无权登录');此时客户端收到的HttpStatus为200,表示协议层请求成功,但业务层返回错误。前端在处理response时,可以直接检查errcode是否为0来判断请求是否成功。自定义异常过滤器虽然内置的异常过滤器可以自动处理很多情况,但是它不是“可编程的”,这意味着我们无法完全控制异常处理过程。如果我们需要记录日志,我们可以使用内置的异常过滤器来完成。不,这时候你可以使用@Catch注解来自定义异常处理器,添加日志记录什么的。import{ExceptionFilter,Catch,ArgumentsHost,HttpException}from'@nestjs/common';import{Request,Response}from'express';@Catch(HttpException)exportclassHttpExceptionFilterimplementsExceptionFilter
