typescript - Angular/RxJS - Finns det ett RxJS-pipe för startad ström?
Jag försöker skapa ett sätt att visa och dölja laddningsskärmen dynamiskt när jag löser någon ström.
Här är min nuvarande kod:
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)
}
)
Det förväntade resultatet är att när min ström startar, visas en laddningsskärm med startLoading() och när operationen är klar, döljs laddningen med endLoading().
Min fungerande kod:
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)
}
)
Använder jag denna tap-pipe korrekt? Finns det en annan pipe som löser detta bättre?
Vad är det bästa sättet att göra detta med RxJS?
Svar #1
I ditt första exempel kör din tap efter att din HTTP-förfrågan har slutförts.
I slutändan skulle du bara kalla this.startLoading() innan du startar HTTP-förfrågan.
this.startLoading();
this.requestService.get<Checkout>(`check/${orderNumber}`).pipe(
finalize(() => this.endLoading())
).subscribe(() => {
});
Om du verkligen vill kalla this.startLoading() i en pipe kan du kalla den innan HTTP-förfrågan startar genom att börja med din egen observable:
return of(null).pipe(
tap(() => this.startLoading()),
concatMap(() => this.requestService.get<Checkout>(`check/${orderNumber}`)),
finalize(() => this.endLoading())
).subscribe(() => {
});
Men då är det egentligen inte mycket poäng med att göra det.
Så din tap-syntax är korrekt, det är bara det att den inte körs när du tror att den borde.
Svar #2
Om du vill utföra bieffekter på varje observerbar prenumeration kan du omvandla källan med defer().
import { defer } from 'rxjs';
...
defer(() => {
this.startLoading();
return this.requestService.get<Checkout>(`check/${orderNumber}`);
}).pipe(
finalize(() => this.endLoading())
)
.subscribe(...);
