包装rxjs可以观察到前后的操作例如显示/隐藏加载屏幕

问题描述

我正在尝试创建包装给定Observable的函数,并为其添加加载屏幕。
函数function wrapWithLoadingScreen<T>(obs$: Observable<T>): Observable<T>的工作方式应为:

  1. 显示加载屏幕。
  2. 执行可观察到的参数
  3. 发出所有值后隐藏加载屏幕。

我最初的实现想法是:

function wrapWithLoadingScreen<T>(obs$: Observable<T>): Observable<T> {
  return of(null).pipe(
    tap(() => console.log("show loading screen")),switchMap(() => obs$),finalize(() => console.log("hide loading screen"))
  );
}

但是当我将其他运算符链接到该函数的结果时,则在这链接后执行“隐藏加载屏幕”(而不是在原始可观察的完成之后)。

这里是一个示例:https://stackblitz.com/edit/rxjs-wrapping-observable

上面的控制台中的结果是

show loading screen
im reducing
im reducing
reducing finished so loading screen should be hidden
the result is 6
hide loading screen

我的目标应该是

show loading screen
im reducing
im reducing
hide loading screen
reducing finished so loading screen should be hidden
the result is 6

解决方法

这是因为finalize是在拆解之后执行的,请参阅此GitHub Issue以获取更多信息。这意味着即使您在链的中间使用finalize,甚至在reducemergeMap之前,它也会在拆卸过程中最后执行。

对于您的问题的替代解决方案,您可以像这样使用tap

function wrapWithLoadingScreen<T>(obs$: Observable<T>): Observable<T> {
  return of(null).pipe(
    tap(() => console.log("show loading screen")),switchMap(() => obs$),tap(
      () => {},() => console.log("hide loading screen"),() => console.log("hide loading screen")
    ),);
}

除了next回调外,您还可以向error运算符提供completetap回调。有关错误和完整的回调的更多信息,请参见RxJS Tap Doc