嗯..很久没写技术文章了哈哈哈。众所周知,Nestjs自己提供了一个异常过滤器,使用一个ExceptionFilter类可以在发生问题的时候额外输出多一些内容,那么久比如说:修改返回的数据结构,又或者是碰到错误的时候,及时使用Logger生成日志

如图,就是一个Logger.log返回的信息

image-20220114063844720

从 implements 开始

众所周知,nest提供了一个ExceptionFilter的基础类,而要写出自定义的过滤器,也只需要 implements ExceptionFilter 即可

类内部,为了捕捉错误等一系列操作,我们要用到catch()方法,在此处定义两个变量,分别为exception和host

host 变量

其中自然就要对这两个变量做一个注解了,exception我们都知道,但是host将会用到一个叫做「ArgumentsHost」的类

ArugumentsHost 提供了在Express中的request, response, next(或者说封装了他们)

我们大可以用switchToHttp方法来获取他们

而目前,我们的代码是这个样子的:

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    //...
  }
}

接下来就首先处理一下host吧

const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();

上面的代码中,我们使用switchToHttp方法(它的作用是将上下文转变为HTTP),将host转移到了ctx,此时ctx的类型就变成了:HttpArgumentsHost

处理过后,我们就可以在后面使用啦~接下来我们来看看「exception」

exception 变量

那这个就简单了

  • exception.message可以获取异常信息
  • exception.getStatus()可以获取状态码

综合这两条,我们就可以写出来类似于这个的代码

const message = exception.message;
Logger.log('Oops! w(゚Д゚)w 出错了! 错误信息: ' + message);
const errorResponse = {
  statusCode: exception.getStatus(),
  message: message,
  error: message,
  url: request.originalUrl,
};

当然这个时候我们只是写好了这些量,但是他们全都没有被真正在返回数据中使用到

而这个时候,我们在前面处理host时出来的「response」就有了用途

我们可以通过response设置返回的状态码、头、错误信息

response.status(status);
response.header('Content-Type', 'application/json; charset=utf-8');
response.send(errorResponse);

哦对,返回的状态码还需要检查一下再去返回,毕竟返回的数据无法确定。其中用到的instanceof是来检测某个对象是不是另一个对象的实例的

const status =
  exception instanceof HttpException
    ? exception.getStatus()
    : HttpStatus.INTERNAL_SERVER_ERROR;

那么整体下来,代码就如同这样了

整合为一

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();

    const message = exception.message;
    Logger.log('[gSpaceHelper] Oops! w(゚Д゚)w 出错了! 错误信息: ' + message);
    const errorResponse = {
      statusCode: exception.getStatus(),
      message: message,
      error: message,
      url: request.originalUrl, // 错误的url地址
    };
    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;
    // 设置返回的状态码、请求头、发送错误信息
    response.status(status);
    response.header('Content-Type', 'application/json; charset=utf-8');
    response.send(errorResponse);
  }
}

提升为全局过滤器

前往main.ts文件,将刚刚写的HttpExceptionFilter引入,接着使用useGlobalsFilters创建一个对象吧

app.useGlobalFilters(new HttpExceptionFilter());