nestjs 相关
前略,异常相关
基类:·HttpException·全局异常过滤器;默认未经过处理的异常会被全局异常过滤器或其子类捕获处理;但是如果抛出的异常不属于基类或其子类,会被封装成以下信息并返回;
1
2
3
{
"statusCode": 500,
"message": "Internal server error"
基类·HttpException·
刚已经提过了,这个类从·@nestjs/common·引入,辅助的一般还需要引入辅助枚举类·HttpStatus·,枚举我们常见的·HTTP·响应状态码(200+, 300+, 400+)
等;
最普通的抛出异常:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// controller
import{ HttpStatus, HttpException } from '@nestjs/common';
// ...
@Get()
async f() {
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}
// client
{
"statusCode": 403,
"message": "Forbidden"
}
基类的参数有两个:参数 1·response: string | object·响应体,传入·string·时,·response: {statusCode: 200, message: string},传入·object·时,会直接使用传入的对象序列化后的字符串作为返回主体;参数 2·status·,·HTTP·的状态码;实例: |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// controller
import{ HttpStatus, HttpException } from '@nestjs/common';
// ...
@Get()
async f() {
throw new HttpException({
code: HttpStatus.FORBIDDEN,
msg: 'Forbidden'
}, HttpStatus.FORBIDDEN);
}
// client
{
"code": 403,
"msg": "Forbidden"
}
自定义异常
一般要自定义异常处理,我们可以从基类·HttpException·继承一个自定义的异常类,这样框架底层可以识别这个异常,就是前面说的可以被子类捕获的。看个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// forbidden.exception.ts
import { HttpException, HttpStatus } from '@nestjs/common';
export class ForbiddenException extends HttpException {
constructor(parameters?) {
super('Forbidden', HttpStatus.FORBIDDEN);
}
}
// controller
class CatController {
addCats() {
throw new ForbiddenException();
}
}
异常过滤器
场景:对异常层有完全控制的情况,常见的有为异常添加日志等,过滤器可以让开发者控制流和响应的内容。
我们使用基类异常来作为需要过滤的异常,这意味着我们将创建一个专门处理·HttpException·异常的控制器。那因为我们要自定义响应内容,所以我们需要访问底层·request response·;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
// @Catch 表示要过滤的是哪一类异常,这个参数可以用逗号隔开,过滤多种异常类
@Catch(HttpException)
// 捕获类的基类ExceptionFilter,其实是个接口,接口要求实现catch方法
export class HttpExceptionFilter implements ExceptionFilter {
/**
* @desc: 需要实现的catch方法
* @param {HttpException} exception 过滤的异常实例
* @param {ArgumentsHost} host 这个参数在后面会单独介绍,现在只要知道它是个封装对象,包含了很多底层信息,可以用这个参数来拿到底层的request response
* @author: youzi
*/
catch(exception: HttpException, host: ArgumentsHost) {
// 调用该方法返回的对象是HttpArgumentsHost
const ctx = host.switchToHttp();
// 返回底层的请求和响应两个对象
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
// 获取异常状态码
const status = exception.getStatus();
response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}