Nest框架中的拦截器

228 阅读2分钟

拦截器是使用 @Injectable() 装饰器注解的类。拦截器应该实现 NestInterceptor 接口

创建拦截器

执行$ nest g interceptor userInterceptor,创建一个名为 userInterceptor 的拦截器

$ nest g interceptor userInterceptor

创建一个拦截器实例

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
// 定义了一个名为TransformInterceptor的拦截器,该拦截器实现了NestInterceptor接口,并使用了泛型T和Response
export class LoggingInterceptor implements NestInterceptor {
  // 实现了NestInterceptor接口中的intercept方法,该方法接收两个参数:执行上下文 和 调用处理程序
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Before...');

    const now = Date.now();
    // 通过调用next.handle()方法获取到调用处理程序返回的数据
    return next
      .handle()
      .pipe(
        tap(() => console.log(`After... ${Date.now() - now}ms`)),
      );
  }
}

注入器(Injectable)

拦截器(NestInterceptor)

执行上下文(ExecutionContext)

调用处理程序(CallHandler)

绑定拦截器

绑定的方法和Nest框架守卫Nest框架过滤器一样

方法一:类型绑定

@Get()
// 传递的型
@UseInterceptors(LoggingInterceptor)
export class CatsController {}

方法二:实例绑定

@Get()
// 传递实例
@UseInterceptors(new LoggingInterceptor())
export class CatsController {}

全局拦截器

全局拦截器绑定在主模块中

const app = await NestFactory.create(ApplicationModule);
app.useGlobalInterceptors(new LoggingInterceptor());

响应映射

该拦截器的作用是将响应数据封装为一个标准的Response对象,并返回给客户端。

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Response<T> {
  data: T;
}

@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
  intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
    return next.handle().pipe(map(data => ({ data })));
  }
}

假设我们需要将每个发生的 null 值转换为空字符串 ''

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable()
export class ExcludeNullInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next
      .handle()
      .pipe(map(value => value === null ? '' : value ));
  }
}

异常映射

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  BadGatewayException,
  CallHandler,
} from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable()
export class ErrorsInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next
      .handle()
      .pipe(
        catchError(err => throwError(new BadGatewayException())),
      );
  }
}

实例:

假设要处理路由请求超时。如果端点在一段时间后未返回任何内容,则将以错误响应终止。

import { Injectable, NestInterceptor, ExecutionContext, CallHandler, RequestTimeoutException } from '@nestjs/common';
import { Observable, throwError, TimeoutError } from 'rxjs';
import { catchError, timeout } from 'rxjs/operators';

@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      timeout(5000),
      catchError(err => {
        if (err instanceof TimeoutError) {
          return throwError(new RequestTimeoutException());
        }
        return throwError(err);
      }),
    );
  };
};