When I subscribe to getAllSubModules forkJoin executes all those observables without error but does not complete. I know forkJoin completes only after all its observables completed but as a proof I see '-----' 3 times in console which confirm everything is successful so all its observables completed.
getSubmodules(id): Observable<any> {
return this.authService.getToken()
.flatMap((token) => this.http.get(`${this.URL}/ROS/applications/modules/${id}/subModules?token=${token}`))
.map((res: any) => res.data.map((subModule) => this.mapSubModules(subModule)));
}
getAllSubmodules(): Observable<any> {
const tasks = [];
this.modules.forEach((module: AppModule) => {
const obs = this.getSubmodules(module.id).map((subModules) => {
this.allSubModules[module.id] = subModules;
console.log('--------------------');
});
tasks.push(obs);
});
return Observable.forkJoin(...tasks).retry(2);
}
mapSubModules(moduleData) {
if (moduleData.id) {
const subModule = <SubModule> {
id: moduleData.id,
parentId: moduleData.parentId,
typeId: moduleData.typeId,
name: moduleData.name.az,
active: true
};
return subModule;
}
}
This code is not executed when using forkJoin:
this.universityService.getAllSubmodules().subscribe(() => {
// --- Below is not executed!--
console.log('subModules in Report Co');
console.log(this.universityService.allSubModules);
this.checkUrl();
this.showChild = true;
}, (er) => console.log(er));
but when I use combineLatest instead of forkJoin it works as expected. So what is problem?Hope someone give advice.
If no input observables are provided (e.g. an empty array is passed), then the resulting stream will complete immediately. forkJoin will wait for all passed observables to emit and complete and then it will emit an array or an object with last values from corresponding observables.
Be aware that if any of the inner observables supplied to forkJoin error you will lose the value of any other observables that would or have already completed if you do not catch the error correctly on the inner observable.
It's worth noting that the forkJoin operator will preserve the order of inner observables regardless of when they complete.
In fork/join patterns, work is forked (split) into a set of tasks that can be executed asynchronously.
In order for the resulting array to have the same length as the number of input observables, whenever any of the given observables completes without emitting any value, forkJoin will complete at that moment as well and it will not emit anything either, even if it already has some last values from other observables.
If any given observable errors at some point, forkJoin will error as well and immediately unsubscribe from the other observables. Optionally forkJoin accepts a resultSelector function, that will be called with values which normally would land in the emitted array.
If no input observables are provided (e.g. an empty array is passed), then the resulting stream will complete immediately. forkJoin will wait for all passed observables to emit and complete and then it will emit an array or an object with last values from corresponding observables.
That means forkJoin will not emit more than once and it will complete after that. If you need to emit combined values not only at the end of the lifecycle of passed observables, but also throughout it, try out combineLatest or zip instead.
Your expectation is incorrect. Having console.log('--------------------')
emitted 3 times only means that you have received 3 onNext
events. forkJoin
waits for all observables to complete.
Try what happens if you look at the individual streams with .do(next=>{},err=>{},complete => console.log('completed'))
or explicitly define when your streams should complete using .take(1)
and/or .timeout(1000)
.
Does authService..getToken()
complete after emitting one value?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With