NestJS:拦截地图和catchError

Posted

技术标签:

【中文标题】NestJS:拦截地图和catchError【英文标题】:NestJS : Interceptor both map and catchError 【发布时间】:2019-11-17 14:13:38 【问题描述】:

我需要一个 NestJS 拦截器来归档请求,无论是在异常情况还是快乐路径情况下。创建如下:

public intercept(context: ExecutionContext, next: CallHandler): Observable<any> 

    if (!this.reflector.get<boolean>(RequestMetaData.IS_PUBLIC_ROUTE, context.getHandler())) 
        return next.handle().pipe(
          map(data => 
              const host = context.switchToHttp();
              const req = host.getRequest();
              const resp = host.getResponse();
              this.persistRequest(data, req, resp)
                .then(() => this.logger.log(`Request logged`))
                .catch(e => 
                    this.logger.error(`Error logging request: $e.message`);
                );
              return data;
          ));
    
    return next.handle();

问题:

这只会记录快乐的路径。因为我不熟悉 RxJS,所以我创建了另一个来持久化错误。例如:

public intercept(context: ExecutionContext, next: CallHandler): Observable<any> 
    return next
      .handle()
      .pipe(
        catchError(err => 
            return throwError(err);
        )
      );

如何定义一个归档两个路径的拦截器?

【问题讨论】:

【参考方案1】:

我认为您在这里使用了错误的运算符。内部地图也返回一个发布者。

您应该使用flatMap 转换外部发布者,以便创建一个流,而不是嵌套流。

这是纯 RxJS 6 中的示例:

import  of, EMPTY  from 'rxjs';
import  map, flatMap, catchError  from 'rxjs/operators';

of(3,2,1,0,1,2,3).pipe(
  flatMap(v => 
    return of(v).pipe(
      map(x =>     
        if(x===0) throw Error();
        return 6 / x;
      ), 
      catchError(error => 
        console.log("Shit happens")
        return EMPTY
      
    )
    )
   
))
.subscribe(val => console.log("Request " + val + " logged "));

每个请求(这里是数字)都是平面映射到一个持久化的东西。 平面图意味着持久化器再次返回一个可观察对象。见https://rxjs-dev.firebaseapp.com/api/operators/flatMap

这些内部可观察对象的错误处理是通过catchError 运算符完成的。它记录错误,然后返回一个空的 observable 以指示内部 observable 是“死的”。你可以在这里返回另一个 observable,然后内部会继续。

外部的 observable,也就是你传入的请求,会一直持续下去。

我在这里创建了一个 stackblitz 应用程序:

https://rxjs-qkqkm2.stackblitz.io

祝 NestJS 和所有不同版本的 RxJS 好运。以上是第6版。

编辑:

RxJS tap 方法是处理副作用的好方法。实现拦截方法如下:

public intercept(context: ExecutionContext, next: CallHandler): Observable<any> 

    if (!this.reflector.get<boolean>(RequestMetaData.IS_PUBLIC_ROUTE, context.getHandler())) 

        const host = context.switchToHttp();
        const req = host.getRequest();
        const resp = host.getResponse();

        return next.handle().pipe(
          tap(
              next: (val) => 
                  this.persistRequest(val, req, resp);
              ,
              error: (error) => 
                  this.persistRequest(AppError.from(error), req, resp);
              
          )
        );
    
    return next.handle();

【讨论】:

嘿迈克尔!情况如何?你愿意提供一个例子吗?我没有关注。 一切都很好。我已经更新了我的答案以澄清这个概念。希望对您有所帮助。 我最终使用了 tap - 感谢您为我指明了正确的方向。顺便说一句,我使用的最后一个 FRP 框架是用于 Objective-C 的——我认为它被称为 Reactive Cocoa。

以上是关于NestJS:拦截地图和catchError的主要内容,如果未能解决你的问题,请参考以下文章

NestJS Swagger:在 ApiProperty 装饰器中描述地图

Angular intercept catcherror 还会捕获除 404 之外的其他错误,并阻止应用按原样工作

如何在 NestJS 拦截器中获取处理程序路由(对于 Express 和 Fastify)

如何测试 Nestjs 拦截器?

NestJs - 如何在拦截器上获取请求正文

vue 使用 腾讯地图api