Nestjs相关笔记

Posted by Youzi Blog on July 30, 2020

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,
      });
  }
}