Reputation: 724
I have a couple of methods in the form of
getFirstDataBunch() {
return this.repository.getData(this.parameter).pipe(
switchMap(
result => {
//Do something with result;
return of(true);
}
)
);
}
Which I then call on my ngOnInit
as:
function ngOnInit(){
forkJoin(this.getFirstDataBunch(), this.getSecondDataBunch(), this.getThirdDataBunch()).subscribe(
results => {
//do stuff with results;
}
);
}
I can see that all the observables are being called, and they return an observable, however the forkJoin
Subscribe method is never called, from what I've read forkJoin
fires only when all observables return and are finished, and I do believe that to be the case, so why is not firing?
I've also seen that some people simply go for combineLatest
, but because these methods only return once I don't really need to keep looking for updates on them.
Upvotes: 2
Views: 3304
Reputation: 2510
your methods are not completed, you should complete it manually via first()
operator or take(1)
.
function ngOnInit(){
forkJoin(
this.getFirstDataBunch().pipe(first()),
this.getSecondDataBunch().pipe(first()),
this.getThirdDataBunch().pipe(first())
).subscribe(
results => {
//do stuff with results;
}
);
}
Upvotes: 8
Reputation: 1679
I would simply use the combination operator that you want/need and pipe it with a take(1)
.
Why the take()
operator?
Because take returns an Observable that emits only the first X values emitted by the source Observable. We set how many emissions.
Example:
import { of } from 'rxjs';
import { take } from 'rxjs/operators';
//emit 1,2,3,4,5
const source = of(1, 2, 3, 4, 5);
//take the first emitted value then complete
const example = source.pipe(take(1));
//output: 1
const subscribe = example.subscribe(console.log);
//output: 1, 2, 3
const example2 = source.pipe(take(3)).subscribe(console.log);
If you want to be 100% sure to avoid any possible memory leak, I suggest using also takeUntil()
(since take(1) can be stuck forever for some reason, if the observable never emits)
.pipe(take(1), takeUntil(this.destroy$))
As a general suggestion, place always takeUntil()
as the last argument of your pipe.
About what combination operator:
forkJoin
--> as you wrote, waits for all observables to complete and then emits the last emitted value from each (like a Promise.all
). It would work, but each observable needs to complete (not just emit!).
zip
--> waits for all observables to emit, then emit values as an array (in sequence order - picture below). I would probably use this.
combineLatest
--> Waits for all observables to emit, emits once. Then whenever any input Observable emits a value, it emits the new value of the observable that emitted and the last emission of the others (who didn't emit). Sure, that would work too with take(1)
...
Upvotes: 2