NestJS 拦截器 和 RxJs
为什么要介绍RxJs 因为 在 Nestjs 已经内置了 RxJs 无需安装 并且Nestjs 也会有一些基于Rxjs提供的API
RxJs是什么
RxJs 使用的是观察者模式,用来编写异步队列和事件处理。
Observable 可观察的物件
Subscription 监听Observable
Operators 纯函数可以处理管道的数据 如 map filter concat reduce 等
文档
案例
发布订阅
类似于迭代器 next 发出通知 complete通知完成
subscribe 订阅 observable 发出的通知 也就是一个观察者
import { Observable } from "rxjs";
//类似于迭代器 next 发出通知 complete通知完成
// 可观察的物件
const observable = new Observable(subscriber=>{
// 发出通知
subscriber.next(1)
subscriber.next(2)
subscriber.next(3)
setTimeout(()=>{
subscriber.next(4)
subscriber.complete()
},1000)
})
// 订阅通知
observable.subscribe({
// 每一步都可以检测到
next:(value)=>{
console.log(value)
}
})
定时监听
interval 五百毫秒执行一次 pipe 就是管道的意思
管道里面也是可以去掉接口的支持处理异步数据
去处理数据 这儿展示 了 map 和 filter 跟数组的方法是一样的
最后 通过观察者 subscribe 接受回调
import { interval } from "rxjs";
import { map, filter } from 'rxjs/operators'
// interval 五百毫秒执行一次 pipe 就是管道的意思
// 管道里面也是可以去掉接口的支持处理异步数据
const subs = interval(500).pipe(
map(v => ({ num: v })),
filter(v => (v.num % 2 == 0))
//通过观察者 subscribe 接受回调
).subscribe((e) => {
console.log(e)
// 结束条件
if (e.num == 10) {
subs.unsubscribe()
}
}
)
处理事件
Rxjs 也可以处理事件
不过我们在Nestjs 里面就不用操作DOM 了
你如果Angular 或则 Vue 框架看可以使用 fromEvent
import { fromEvent } from "rxjs";
import { map } from 'rxjs/operators'
const dom = fromEvent(document,'click').pipe(map(e=>e.target))
dom.subscribe((e)=>{
})
拦截器
拦截器具有一系列有用的功能,这些功能受面向切面编程(AOP)技术的启发。它们可以:
- 在函数执行之前/之后绑定额外的逻辑
- 转换从函数返回的结果
- 转换从函数抛出的异常
- 扩展基本函数行为
- 根据所选条件完全重写函数 (例如, 缓存目的)
文档:
https://docs.nestjs.cn/9/interceptors
案例:全局响应格式转换
我们现在没有给我们的Nestjs 规范返回给前端的格式现在比较乱
就是跟下面一样
Hello World!
我们想给他返回一个标准的json 格式
就要给我们的数据做一个全局format
如
{
data, //数据
status:0,
message:"成功",
success:true
}
那要怎么实现呢
创建模块
新建common 文件夹
创建 response.ts
Nest Js 配合 Rxjs 格式化数据
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: "makalo 永远18,永不秃头"
}
}))
}
}
main.ts 中注册
// 注册全局响应拦截-格式转换
app.useGlobalInterceptors(new Response())