包装 rxjs observable 在前后做一些事情(例如 show/hide 加载屏幕)

Wrapping rxjs observable to do something before and after (for example show/hide loading screen)

我正在尝试创建包装给定 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 回调,您还可以向 tap 运算符提供 errorcomplete 回调。有关错误和完整回调的详细信息,请参阅 RxJS Tap Doc