NestJS 拦截器 和 RxJs

发布时间 2023-04-04 15:54:15作者: makalo

为什么要介绍RxJs 因为 在 Nestjs 已经内置了 RxJs 无需安装 并且Nestjs 也会有一些基于Rxjs提供的API

image-20230404093722875

RxJs是什么

RxJs 使用的是观察者模式,用来编写异步队列和事件处理。

Observable 可观察的物件

Subscription 监听Observable

Operators 纯函数可以处理管道的数据 如 map filter concat reduce 等

文档

https://cn.rx.js.org/

案例

发布订阅

类似于迭代器 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)
    }
})

image-20230404100417748

定时监听

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()
    }
}
)

image-20230404102025427

处理事件

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

image-20230404103903226

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,永不秃头"
      }
    }))
  }
}

image-20230404104624742

main.ts 中注册

// 注册全局响应拦截-格式转换
app.useGlobalInterceptors(new Response())

image-20230404104858073

访问测试

image-20230404105132644