When i click on button i am making multiply http request for same api service. If i want to wait for them i am using async await with promises.
NOTE THAT THIS METHOD CALL RETURNS OBSERVABLE !
this.getAuctionService.getAllAuctionsUsingPOST
onButtonClick() {
makeRequest();
makeRequest();
makeRequest();
makeRequest();
}
makeRequest() {
try {
let response: any = this.getAuctionService.getAllAuctionsUsingPOST(params).toPromise()
this.filterService.auctionTotalPages = response.totalPages;
this.currentPage = response.currentPage;
this.remapLazyLoadedData(response, cb);
} catch (error) {
this.toastr.error(error.error.description, error.error.error);
}
}
so when i click on the button four http requests are happening in parallel and that means that sometimes the response from httpRequest number 3 can come earlier then the first one, even it was called later.
Because of this problem i am using now async await with promises
onButtonClick() {
await makeRequest();
await makeRequest();
await makeRequest();
await makeRequest();
}
async makeRequest() {
try {
let response: any = await this.getAuctionService.getAllAuctionsUsingPOST(params).toPromise()
...
} catch (error) {
this.toastr.error(error.error.description, error.error.error);
}
}
now i am awaiting each call and the responses of the calls wwill be always in the same order as they were called.
But i can't find solutuion for this with Observable - rxjs way
How can i await this multiply calls without async and await ?
onButtonClick() {
makeRequest();
makeRequest();
makeRequest();
makeRequest();
}
makeRequest() {
let response: any = this.getAuctionService.getAllAuctionsUsingPOST(params);
....
}
**what i tried**
i tried with `.subscribe` but it does not work - every each call is not waiting for the previous one
I'm not entirely sure where params comes from, but here's what I would do with RxJS.
private singleRequest$ = this.getAuctionService.getAllAuctionsUsingPOST(params).pipe(
tap(response=>{
this.filterService.auctionTotalPages = response.totalPages;
this.currentPage = response.currentPage;
this.remapLazyLoadedData(response, cb);
}),
catchError(error=>{
this.toastr.error(error.error.description, error.error.error);
return EMPTY;
})
)
private multipleRequests$ = interval(1).pipe(
takeUntil(i=>i===4),
concatMap(_=>this.singleRequest$)
)
public onButtonClick(){
this.multipleRequests$.subscribe();
}
First, I declared an observable that calls your service method, and applies new state using the tap() operator.
Next, I declare a second counting observable that starts with 0. Each interval count will call the first observable. Using concatMap() ensures each call to your service method happens in order. Our takeUntil() operator ensures the observable completes when our counter reaches four.
Thus, your component method just needs to subscribe to multipleRequests$ to trigger the event. Since takeUntil() completes the observable, you don't need to worry about unsubscribing.
You can create a single observable that executes multiple in sequence by using concat:
const sequential$ = concat(obs1$, obs2$, obs3$);
So, if the makeRequest() method returned an observable, you could do:
onButtonClick() {
concat(
makeRequest(),
makeRequest(),
makeRequest(),
makeRequest()
)
.subscribe();
}
So makeRequest could look like this:
makeRequest() {
return this.getAuctionService.getAllAuctionsUsingPOST().pipe(
tap(response => {
this.filterService.auctionTotalPages = response.totalPages;
this.currentPage = response.currentPage;
this.remapLazyLoadedData(response, cb);
}),
catchError(({error}) => {
this.toastr.error(error.description, error.error);
return EMPTY;
})
);
}