1、nest.js的异常处理
Nest 框架内部实现了一个异常处理层,专门用来负责应用程序中未处理的异常。
nest.js内置的异常类有:
BadRequestException
UnauthorizedException
NotFoundException
ForbiddenException
NotAcceptableException
RequestTimeoutException
ConflictException
GoneException
HttpVersionNotSupportedException
PayloadTooLargeException
UnsupportedMediaTypeException
UnprocessableEntityException
InternalServerErrorException
NotImplementedException
ImATeapotException
MethodNotAllowedException
BadGatewayException
ServiceUnavailableException
GatewayTimeoutException
PreconditionFailedException
但是这些类全部继承于 HttpException, 所以通常我们抛出异常的写法有如下方法
@Get('test')
public getTest() {
throw new HttpException(
{
status: HttpStatus.FORBIDDEN, //这里面的字段都是定制字段
error: 'This is a custom message',
data: []
},
HttpStatus.NOT_FOUND //http码
);
// throw new HttpException('error', HttpStatus.PARTIAL_CONTENT);
// throw new ForbiddenException(); //禁止访问错误, 参数1表示message, 参数2是一个error, 直接使用内置的异常类
}
注意: 可以使用HttpException进行异常的抛出,也可以使用内置的方法进行异常的抛出
自定义异常类
export class ForbiddenException extends HttpException {
constructor() {
super('Forbidden', HttpStatus.FORBIDDEN);
}
}
使用自定义异常类
@Get()
async findAll() {
throw new ForbiddenException();
}
如果需要在异常中添加指定的数据,比如需要在异常类中添加请求地址,或者参数, 又或者添加日志的写入等,那么可以定义个异常过滤器
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
} from '@nestjs/common';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
//这里可以添加些日志操作
response.status(status).json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
注意: 这里exception中有两个方法,exception.getStatus() exception.getResonse() 一个是获取异常的错误码,一个是获取异常的信息:里面包含错误码以及原本的message
使用异常过滤器的两种方式
@Post()
@UseFilters(new HttpExceptionFilter())
// @UseFilters(HttpExceptionFilter)
async create(@Body() createCatDto: CreateCatDto) {
throw new ForbiddenException();
}
可以定义全局异常过滤器
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
...
app.useGlobalFilters(new HttpExceptionFilter()); // 注意这里只能使用new这个关键字来实现实例化
await app.listen(3000);
}
bootstrap();
通常来讲还有一种方式实现全局异常过滤器
import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_FILTER,
useClass: HttpExceptionFilter,
},
],
})
export class AppModule {}
注意:不管在哪个模块进行声明定义,那么作用范围将是全局的
2、nest.js日志
Nest附带一个默认的内部日志记录器实现,它在实例化过程中以及在一些不同的情况下使用,比如发生异常等等。但是,有时您可能希望完全禁用日志记录,或者提供自定义实现并自己处理消息。为了关闭记录器,我们使用Nest应用程序选项对象。
const app = await NestFactory.create(ApplicationModule, {
//关闭log
logger: false,
//只启用指定的log级别
logger: ['warn', 'error']
});
await app.listen(3000);
注意:log的等级有'log'
, 'error'
, 'warn'
, 'debug'
, 和 'verbose'
.
在某些场景中,我们可能希望在底层使用不同的日志记录器。为此,我们必须传递一个实现LoggerService接口的对象。例如,一个内置的控制台。
const app = await NestFactory.create(ApplicationModule, {
logger: console,
});
await app.listen(3000);
但这不是一个最好的办法,我们也可以选择创建自定义的记录器:
import { LoggerService } from '@nestjs/common';
export class MyLogger implements LoggerService {
log(message: string) {}
error(message: string, trace: string) {}
warn(message: string) {}
debug(message: string) {}
verbose(message: string) {}
}
然后,我们可以MyLogger直接应用实例:
const app = await NestFactory.create(ApplicationModule, {
logger: new MyLogger(),
});
await app.listen(3000);
扩展内置的日志类
很多实例操作需要创建自己的日志。你不必完全重新发明轮子。只需扩展内置Logger类以部分覆盖默认实现,并使用super将调用委托给父类。
import { Logger } from '@nestjs/common';
export class MyLogger extends Logger {
warn(message: string, trace: string) {
// 写入自己的逻辑
super.warn(message, trace);
}
error(message: string, trace: string) {
// 写入自己的逻辑
super.error(message, trace);
}
}
依赖注入
如果要在Logger类中启用依赖项注入,则必须使MyLogger该类成为实际应用程序的一部分。例如,您可以创建一个LoggerModule:
import { Module } from '@nestjs/common';
import { MyLogger } from './my-logger.service.ts';
@Module({
providers: [MyLogger],
exports: [MyLogger],
})
export class LoggerModule {}
一旦LoggerModule在其他地方导入,框架将负责创建Logger类的实例。现在,要在整个应用程序中使用相同的Logger实例,包括引导和错误处理的东西,请使用以下方式:
const app = await NestFactory.create(ApplicationModule, {
logger: false,
});
app.useLogger(app.get(MyLogger));
await app.listen(3000);