NestJS 7.x 折腾记: 异常过滤器,取其精华去其糟粕!比如响应异常数据的包装~
Posted crper
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NestJS 7.x 折腾记: 异常过滤器,取其精华去其糟粕!比如响应异常数据的包装~相关的知识,希望对你有一定的参考价值。
前言
正如官方所说:
内置的异常层负责处理整个应用程序中的所有抛出的异常。
当捕获到未处理的异常时,最终用户将收到友好的响应。
NestJS提供了一波拿来即用的内置异常过滤器;
在@nestjs/common
里面,搜索下Exception就有~
我们来一个具体的例子(全局异常过滤),
基于内置的异常过滤器实现,采用第三方日志(pino)记录异常日志,
做一些处理并包裹返回信息;
效果图
实战
# 基于cli生成filter模板
nest g f common/filters/http-exception
http-exception.filter.ts
// 日期格式化库,很小巧,类moment 风格api
import * as dayjs from 'dayjs';
import
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
HttpStatus,
from '@nestjs/common';
// nest默认底层是基于express封装,所以可以直接引入
import Request, Response from 'express';
// 第三方logger
import Logger from 'nestjs-pino';
// 捕获请求异常类型
// 可以传递多个参数,所以你可以通过逗号分隔来为多个类型的异常设置过滤器。
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter
// 我们要把异常塞到自定义logger,必须引入对应的实例
// 在构建函数声明定义下,从外部传入
constructor(private readonly logger: Logger)
catch(exception: HttpException, host: ArgumentsHost)
// 把请求相关的参数转成标准http的上下文
// 有兴趣可以点进去,GPRC,WEBSOCKET都能直接转换
// 也能直接拿到一些参数的及返回上下文类型
const ctx = host.switchToHttp();
// 响应体
const response = ctx.getResponse<Response>();
// 请求体
const request = ctx.getRequest<Request>();
// 判断状态是否为请求异常,否则直接抛回来服务内部错误
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
// 此刻的时间
const nowDate = dayjs(Date.now()).format('YYYY-MM-DDTHH:mm:ss');
// 包装异常信息
const errorResponse =
statusCode: status,
message: exception.message,
error: exception.name,
date: nowDate,
path: request.url,
;
// 记录异常信息到第三方logger
this.logger.error(
`【$nowDate】$request.method $request.url query:$JSON.stringify(
request.query,
) params:$JSON.stringify(request.params) body:$JSON.stringify(
request.body,
)`,
JSON.stringify(errorResponse),
'HttpExceptionFilter',
);
// 塞回去响应体,也就是客户端请求可以感知到的
response.status(status).json(errorResponse);
主入口(main.ts)
import AppModule from './app.module';
import HttpExceptionFilter from './common/filters/http-exception.filter';
import Logger from 'nestjs-pino';
import NestFactory from '@nestjs/core';
async function bootstrap()
const app = await NestFactory.create(AppModule,
cors: false,
logger: false,
);
// 获取pino logger实例
const logger = app.get(Logger);
// nestjs-pino 取代nest logger
app.useLogger(logger);
// 设置全局异常过滤器
app.useGlobalFilters(new HttpExceptionFilter(logger));
await app.listen(configService.get('SERVE_LISTENER_PORT'));
bootstrap()
app.module.ts
若是只要特定模块生效可以使用Providers去实现,从核心模块导出;
import Module from '@nestjs/common';
// 包括网关,拦截器都可以走这种模式!
import APP_FILTER from '@nestjs/core';
import HttpExceptionFilter from './common/filters/http-exception.filter';
@Module(
providers: [
provide: APP_FILTER,
useClass: HttpExceptionFilter,
,
],
)
export class AppModule
若是加上@Global
装饰器也能达到全局模块的效果!
这个东东一般不推荐用在app.module,而是你需要导出的复用模块!
这里只是演示写法
import Module,Global from '@nestjs/common';
import APP_FILTER from '@nestjs/core';
@Global()
@Module(
providers: [
provide: APP_FILTER,
useClass: HttpExceptionFilter,
,
],
)
export class AppModule
@Global()
推荐用于给外部复用,又需要变成全局模块的,比如
import Module, Global from '@nestjs/common';
import CatsController from './cats.controller';
import CatsService from './cats.service';
@Global()
@Module(
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService],
)
export class CatsModule
总结
有不对之处请留言,会及时修正!谢谢阅读~
以上是关于NestJS 7.x 折腾记: 异常过滤器,取其精华去其糟粕!比如响应异常数据的包装~的主要内容,如果未能解决你的问题,请参考以下文章