NestJS:拦截器同时映射和catchError

时间:2019-07-08 04:46:33

标签: node.js typescript express rxjs nestjs

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

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

问题:

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

{
    "_id": ObjectID("5d224019c947139b4e12652b"),
    "type_errors": [
        {
            "name": "type_error1",
            "sub_type_errors": [
                {
                    "name": "sub_type_error1",
                    "dashboard_activated": 0,
                    "email_activated": 0
                },
                {
                    "name": "sub_type_error2",
                    "dashboard_activated": 0,
                    "email_activated": 0
                }
            ]
        },
        {
            "name": "type_error2",
            "sub_type_errors": [
                {
                    "name": "sub_type_error3",
                    "dashboard_activated": 0,
                    "email_activated": 0
                }
            ]
        }
    ],
    "user": "user1",
    "client": "client1",
    "dashboard_client_activated": 0,
    "email_client_activated": 0
}

如何定义一个可以同时存档两个路径的拦截器?

1 个答案:

答案 0 :(得分: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是“死的”。您可以在此处返回另一个可观察到的值,而不是内部将继续的值。

外部可观察到的内容(即您的传入请求)将继续进行。

我在这里创建了一个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();
}