typescript - Angular/RxJS - 有没有用于流开始的 RxJS pipe?
我正在尝试创建一种方法,在处理某些流时动态显示和隐藏加载屏幕。
这是我目前的代码:
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 做这件事的最佳方式是什么?
答案#1
在你的第一个例子中,当你的 HTTP 请求完成后,你的 tap 才会运行。
最终,你只需在开始 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 语法是正确的,只是它没有在你认为它应该执行的时候执行。
答案#2
如果你想在每个可观察对象的订阅上执行副作用,你可以使用 defer() 包装源。
import { defer } from 'rxjs';
...
defer(() => {
this.startLoading();
return this.requestService.get<Checkout>(`check/${orderNumber}`);
}).pipe(
finalize(() => this.endLoading())
)
.subscribe(...);
