Angular/RxJS-是否有一个RxJS管道用于启动流



我试图创建一种方法,在解析某个流时以普通方式显示和隐藏加载屏幕。

这是我当前的代码:

this.requestService
        .get<Checkout>(`check/${orderNumber}`)
        .pipe(
            tap(() => this.startLoading()),  //i think this isnt the right way to use this pipe
            finalize(() => this.endLoading())
        )
        .subscribe(
            data => {
                data.orderNumber = orderNumber
                this.checkout.next(data)
            },
            error => {
                this.notification.warning(error)
            }
        )

预期的结果是,当我的流开始时,当操作完成时,显示带有startLoading()的加载屏幕结束,使用endLoading()隐藏加载。

我的工作代码:

this.startLoading() //basically calling function before i create the stream
this.requestService
        .get<Checkout>(`check/${orderNumber}`)
        .pipe(                
            finalize(() => this.endLoading())
        )
        .subscribe(
            data => {
                data.orderNumber = orderNumber
                this.checkout.next(data)
            },
            error => {
                this.notification.warning(error)
            }
        )

我是否正确使用此tap管道?还有其他管道可以更好地解决这个问题吗?

使用RxJS最好的方法是什么?

在第一个示例中,您的tap在http请求完成后运行。

最终,您只需要在启动http请求之前调用this.startLoading()

this.startLoading();
this.requestService.get<Checkout>(`check/${orderNumber}`).pipe(
  finalize(() => this.endLoading())
).subscribe(() => {
});

如果您真的想在管道中调用this.startLoading(),您可以在http请求开始之前调用它,方法是从您自己的observable开始:

return of(null).pipe(
  tap(() => this.startLoading()),
  concatMap(() => this.requestService.get<Checkout>(`check/${orderNumber}`)),
  finalize(() => this.endLoading())
).subscribe(() => {
});

但这样做并没有多大意义。

所以你的tap语法是正确的,只是它没有在你认为应该执行的时候执行

如果您想对每个可观察的订阅执行副作用,可以使用defer()扭曲源。

import { defer } from 'rxjs';
...
defer(() => {
  this.startLoading();
  return this.requestService.get<Checkout>(`check/${orderNumber}`);
}).pipe(
    finalize(() => this.endLoading())
  )
  .subscribe(...);

您可以将BehaviorSubject和RxJs deferfinalize管道一起使用,以跟踪加载过程。

import { defer } from 'rxjs';
// ...
public this.loading: BehaviorSubject<boolean> = new BehaviorSubject(false);
// ...
public getOrder(orderNumber): Observable<Checkout> {
  defer(() => {
    this.loading.next(true);
    return this.requestService.get<Checkout>(`check/${orderNumber}`);
  }).pipe(
    finalize(() => this.loading.next(false)
  );
}
// to get boolean from BehaviorSubject -> is loading
public isLoading(): boolean {
  return this.loading.value;
}
// ...

现在,您还可以在类外使用this.loading observable,例如,显示或隐藏基于observable值的加载器:

// logs to console each time loading state changes
serviceName.loading.subscribe(result => console.log(result));

不要忘记以后取消订阅,因为加载器是一个行为主体,它是多播的,如果不取消订阅,会导致内存泄漏。

最新更新