In Angular a page makes multiple http calls on multiple actions, let's say button clicks. But when the last "DONE" button is pressed I want to make sure that all those requests are finished before it progresses. I tried to use forkJoin
with observables but it triggers requests itself which is not what I want to do, I want other actions to trigger requests and just to make sure that async requests are finished when "DONE" is clicked. With promises I would just push promises to array and then do Promise.all(allRequests).then(()=>{})
observables: Observable<any>[];
onBtn1Click(){
let o1 = this.service.doAction1();
this.observables.push(o1);
o1.subscribe(resp => {
//do action1
});
}
onBtn2Click(){
let o2 = this.service.doAction2();
this.observables.push(o2);
o2.subscribe(resp => {
//do action2
});
}
onDoneClick(){
// I would like something like this just that it wouldn't trigger the requests but make sure they are completed.
forkJoin(this.observables).subscribe(()=>{
//Proceed with other things
});
}
Unless someone comes up with an elegant approach, the following should do it.
I'm creating an object to hold hot observable for each cold observable from the HTTP request. The request would emit to it's corresponding hot observable using RxJS finalize
operator. These hot observables could then be combined using forkJoin
with a take(1)
to wait for the source requests to complete.
private httpReqs: { [key: string]: ReplaySubject<boolean> } = Object.create(null);
onBtn1Click() {
this.httpReqs['btn1'] = new ReplaySubject<boolean>(1);
this.service.doAction1().pipe(
finalize(() => this.httpReqs['btn1'].next(true))
).subscribe(resp => {
// do action1
});
}
onBtn2Click() {
this.httpReqs['btn2'] = new ReplaySubject<boolean>(1);
this.service.doAction1().pipe(
finalize(() => this.httpReqs['btn2'].next(true))
).subscribe(resp => {
// do action2
});
}
onDoneClick(){
forkJoin(
Object.values(this.httpReqs).map(repSub =>
repSub.asObservable().pipe(
take(1)
)
)
).subscribe(() => {
// Proceed with other things
});
}