【问题标题】:Using an async method in a RxJS NextObserver在 RxJS NextObserver 中使用异步方法
【发布时间】:2020-05-26 17:02:48
【问题描述】:

我正在尝试在 NestJS 拦截器中使用异步函数。这些拦截器像这样使用 RxJS Observables:

@Injectable()
export class MyInterceptor implements NestInterceptor {
    async intercept<T>(context: ExecutionContext, next: CallHandler): Promise<Observable<T>> {
        await doBegin();
        return next
            .handle()
            .pipe(
                tap(
                    () => console.log("Done"),
                    (e) => console.error(e)
                )
            );
    }
}

这可行,但是如果我希望tap 中的方法是异步的怎么办? method signature 是:

(value: T) => void

我可以在里面放一个异步方法吗?还是我应该采取不同的方法?

【问题讨论】:

    标签: async-await rxjs nestjs


    【解决方案1】:

    如果您希望它是异步的并且应该捕获它的错误,您需要使用mergeMap 或任何其他合适的运算符在流上下文中处理它,因为tap 会导致流之外的副作用。

    const myAsyncFunction = () => {
      // a sample of promise.
      return new Promise(resolve => {
        setTimeout(() => {
          console.log('Promise!');
          resolve();
        }, 1000);
      });
    }
    
    @Injectable()
    export class MyInterceptor implements NestInterceptor {
        async intercept<T>(context: ExecutionContext, next: CallHandler): Promise<Observable<T>> {
            await doBegin();
            return next
                .handle()
                .pipe(
                    mergeMap(value => from(myAsyncFunction()).pipe(
                      ignoreElements(),
                      // catchError(() => EMPTY), // catching all errors.
                      endWith(value),
                    )),
                    tap(
                      () => {}, // nothing to do here, we need error.
                      (e) => console.error(e), // or catchError if you wan't to handle it.
                    ),
                );
        }
    }
    

    如果您不关心它的错误 - 只需致电 .then

    @Injectable()
    export class MyInterceptor implements NestInterceptor {
        async intercept<T>(context: ExecutionContext, next: CallHandler): Promise<Observable<T>> {
            await doBegin();
            return next
                .handle()
                .pipe(
                    tap(
                      myAsyncFunction, // if it returns `new Promise` - it will work.
                      (e) => console.error(e),
                    ),
                );
        }
    }
    

    【讨论】:

    • 我很好奇添加 then() 会有什么帮助?它不只是返回一个 Promise 吗?为什么会和() =&gt; myAsyncFunction()不一样?
    • myAsyncFunction() 返回一个 promise,myAsyncFunction().then() 触发它的执行。当然取决于 promise 是如何编写的,但为了确保它真的被触发,最好调用.then,它有点像await Promise。如果它是一个正确的承诺,那么myAsyncFunction() 只会返回它的指针,但不会触发它。
    • 其实你是对的,在new Promise的情况下你不需要.then。我对我当前的项目感到困惑 :) 我们需要一个 .then 调用来触发原始回调。
    • 我在本地项目中尝试过这个(没有 NestJS)。这两种技术似乎都有效,但合并映射在 IMO 上的效果更好。在这种情况下,在我记录可观察流的结果之前调用异步函数。在第二种情况下,我的异步函数被执行,但在记录流的结果之后。因为我在 AWS Lambda 中工作,我不确定是否会执行事件循环的其余部分,所以我将尝试使用 mergeMap 技术。
    • AWS Lambda 在这两种情况下都会等待它,我过去有过它的经验。 Node 有一个事件循环,用于检查是否有事情要做:youtube.com/watch?v=8aGhZQkoFbQ,无论如何我也会投票给 mergeMap,因为它具有更好的错误处理能力。
    猜你喜欢
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    相关资源
    最近更新 更多