拦截器具有一组有用的功能,这些功能的灵感来自面向方面的编程 (AOP) 技术。拦截器的作用是:
1. 在方法执行之前/之后绑定额外的逻辑
2. 转换函数返回的结果
3. 转换函数抛出的异常
4. 扩展基本功能行为
5. 根据特定条件完全覆盖函数(例如,出于缓存目的)
第一步:创建拦截器
logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const response = context.switchToHttp().getResponse();
console.log('Before...');
return next.handle();
}
}其中 next.handle() 方法之前是请求拦截之前的处理逻辑,常用的是处理request 请求;next.handle() 方法之后是处理拦截之后的逻辑,常常用来修改response 的返回逻辑,这里使用到Rxjs 库。
Rxjs是一种响应式编程(RP)的实现框架。其中Observable字面意识是可观察,所谓的观察就是当事件发生时,由事件发生之前的所指派的函数来处理数据输入。这个指派的过程就是订阅,而事件的发生过程是一个发布。即提前定义好相应发生后的逻辑,待数据流发生后使用之前定义好的逻辑处理,这个流中会三种类型的值,分别是正常产生的值,被触发的异常和整个流结束信号。
创建数据流的方法有:
fromEvent() 和 of()
管道操作方法:
// Observable.pipe(op1,op2,op3...) map:可以修改输入的值,再输出。类似于JS的map函数; tap:每次输入值后接收,但不改变值; timeout:设置一个过期时间,当这个时间段内没有接收到完成信号就会出发这个逻辑; catchError:当管道中发生异常(throw)后,执行的操作;
第二步:nest绑定引入拦截器
// user.controller.ts
@UseInterceptors(LoggingInterceptor)
export class UserController {}全局引入:
// main.ts // 方法一: const app = await NestFactory.create(AppModule); app.useGlobalInterceptors(new LoggingInterceptor());
// app.module.ts
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
// 方法二:
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
},
],
})
export class AppModule {}import {CallHandler, ExecutionContext, Injectable, NestInterceptor} from '@nestjs/common';
import {catchError, map, Observable, of} from 'rxjs';
import {tap} from 'rxjs/operators';
@Injectable()
export class UserInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const response = context.switchToHttp().getResponse();
console.log('Before...');
return next.handle().pipe( // next.handle() 返回Observable对象
tap((data) => console.log('After...', data)), // tap作用接收response 返回值,不做任何处理
map(() => { // map为接受response 返回值,并处理后输出
return {res: 2};
}),
timeout(1000), // 超时定义
catchError(err => { // 异常捕获,可以输出
return of({res: 3});
})
);
}
}客户端在正常http 请求之后,终端可以看到先后执行顺序为:
Middleware ===> 中间件先执行
guard here /user ===> 随后守卫
Before... ===> 拦截器相应前的处理(多是request)
index query Person { name: 'ljd', age: 12 } ===> 正常相应结果
After... { res: 2 } ===> response 后的逻辑处理,这里看到上面After 输出并在浏览器看到了修改后的res: 2结果www.haizhuan.tk