NestJS之10- 拦截器

673 阅读2分钟

1. 实现统一响应返回

拦截器具有一系列有用的功能,这些功能受面向切面编程(AOP)技术的启发。它们可以:

  • 在函数执行之前/之后绑定额外的逻辑
  • 转换从函数返回的结果
  • 转换从函数抛出的异常
  • 扩展基本函数行为
  • 根据所选条件完全重写函数 (例如, 缓存目的)

我们现在没有给我们的Nestjs 规范返回给前端的格式现在比较乱, 我们可以通过 @nestjs/common 包中的 @Injectable() 装饰器和 @nestjs/common 包中的 NestInterceptor 接口类类实现自定义的响应拦截器。

{
  data, //数据
  status:0,
  message:"成功",
  success:true
}

新建common 文件夹 创建 response.ts

import { Injectable, NestInterceptor, CallHandler } from '@nestjs/common'
import { map } from 'rxjs/operators'
import {Observable} from 'rxjs'
 
interface data<T>{
    data:T
}
 
@Injectable()
export class Response<T = any> implements NestInterceptor {
    intercept(context, next: CallHandler):Observable<data<T>> {
        return next.handle().pipe(map(data => {
            return {
               data,
               status:0,
               success:true,
               message:"成功"
            }
        }))
    }
}

上述代码中的 ResponseInterceptor 是一个用于统一响应结果的响应拦截器,通过 map() 运算符改变响应结果格式,并在结果中添加固定的格式。

使用方式

  1. 在main.ts 全局注册
import { Response } from './common/response';

app.useGlobalInterceptors(new Response())

image.png

  1. 单个接口注册

app.controller.ts

import { Controller, Get, Inject, UseInterceptors } from '@nestjs/common';
import { AppService } from './app.service';
import { Response } from './common/response';
import { UserService } from './user/user.service';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    private readonly userService: UserService,
  ) {}

  @Get()
  @UseInterceptors(Response)
  getHello(): object {
    return this.value;
  }

  @Get('user')
  getUser(): string {
    return this.userService.findAll();
  }
}

image.png

image.png

这样就可以针对单个接口做响应返回

2. 实现异常拦截器

方式同上

common中新建一个 filter.ts

import {
  Catch,
  ExceptionFilter,
  ArgumentsHost,
  HttpException,
} from '@nestjs/common';
import { Request, Response } from 'express';

@Catch(HttpException)
export class HttpFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const request = ctx.getRequest<Request>();
    const response = ctx.getResponse<Response>();
    const status = exception.getStatus();
    response.status(status).json({
      data: exception.message,
      time: new Date().getTime(),
      success: false,
      path: request.url,
      status,
    });
  }
}



使用

  1. main.ts 引入全局使用
import { NestFactory } from '@nestjs/core';
// import { NextFunction, Response, Request } from 'express';
import { AppModule } from './app.module';
import { Response } from './common/response';
import { HttpFilter } from './common/filter';


async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new Response());
  app.useGlobalFilters(new HttpFilter());
  await app.listen(3000);
}
bootstrap();

请求http://localhost:3000/upload/1/123/123 不存在的地址

image.png

  1. 单个接口使用

直接传入类即可,不需要调用

import {
  Controller,
  Get,
  Inject,
  UseInterceptors,
  UseFilters,
  NotFoundException,
} from '@nestjs/common';
import { AppService } from './app.service';
import { Response } from './common/response';
import { UserService } from './user/user.service';
import { HttpFilter } from './common/filter';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    private readonly userService: UserService,
  ) {}

  @Get()
  @UseInterceptors(Response)
  @UseFilters(HttpFilter)
  getHello(): object {
    throw new NotFoundException('111');
  }

  @Get('user')
  getUser(): string {
    return this.userService.findAll();
  }
}


上述代码中,NotFoundException 是 Nest.js 中的一个针对 HTTP 请求状态码为 404 的异常,这里我们可以使用 HttpExcepionFilter 拦截它,并返回自定义的错误信息。