Reputation: 19220
I'm wondering what are the differences between Observable.combineLatest
and Observable.forkJoin
?
As far as I can see, the only difference is forkJoin
expects the Observables to be completed, while combineLatest
returns the latest values.
Upvotes: 152
Views: 101145
Reputation: 1153
There are multiple identical (but different) operators in RxJS. Some of them are:
single()
, take(1)
and first()
map()
, switchAll()
and switchMap()
merge()
, mergeAll()
and mergeMap()
concat()
, concatAll()
and concatMap()
window()
and buffer()
forkJoin()
, combineLatest()
and zip()
What forkJoin()
does is, it taking a group of Observables and let them complete emission, once it's completed, as an array, it emits the last value of each Observable. Check the below example:
const observable1$ = new Subject<number>();
const observable2$ = new Subject<number>();
forkJoin([observable1$, observable2$])
.subscribe(([val1, val2])
=> console.log(val1, val2));
observable1$.next(2024);
observable2$.next(2025);
observable1$.next(2026);
observable2$.next(2027);
// The Observables need to be completed
observable1$.complete()
observable2$.complete()
Output:
[2026, 2027]
What combineLatest()
does is hesitating until all observables complete emitting a value as an array. Since that point, it emits an array each time an observable emits a value. Check this simple example:
const observable1$ = new Subject<number>();
const observable2$ = new Subject<number>();
combineLatest([observable1$, observable2$])
.subscribe(([val1, val2])
=> console.log(val1, val2));
observable1$.next(2024);
observable2$.next(2025);
observable1$.next(2026);
observable2$.next(2027);
Output:
[2024, 2025]
[2026, 2025]
[2026, 2027]
What zip()
does is, taking a group of observables and waiting until all observables complete emitting a value then emit all in an array. Check the below example:
const observable1$ = new Subject<number>();
const observable2$ = new Subject<number>();
zip(observable1$, observable2$)
.subscribe(([val1, val2])
=> console.log(val1, val2));
observable1$.next(2024);
observable2$.next(2025);
observable1$.next(2026);
observable2$.next(2027);
Output:
[2024, 2025]
[2026, 2027]
For your reference:
Merging http observables using forkjoin
https://medium.com/geekculture/my-top-6-similar-but-different-rxjs-operators-52241096ef96
Upvotes: 2
Reputation: 15204
forkJoin - When all observables are completed, emit the last emitted value from each.
combineLatest - When any observable emits a value, emit the latest value from each.
Usage is pretty similar, but you shouldn't forget to unsubscribe from combineLatest unlike forkJoin.
Upvotes: 53
Reputation: 1666
There is a situation in Angular which would explain it better. Assume there is a change detection in Angular component, so the latest value is changed. In the pipe
and tap
methods of combineLatest
, the code will be triggered as well. If the latest value is changed N
times by the change detection, then the tap
methods is also triggered N
times as well.
Upvotes: 2
Reputation: 145920
runs observables in parallel, emitting a value each time an observable emits a value after all observables have emitted at least one value.
runs observables in parallel, and emits a single value once all observables have completed.
If any of the observables error out - with combineLatest
it will emit up to the point the error is thrown. forkJoin
will just give back an error if any of the observables error out.
Advanced note: CombineLatest doesn't just get a single value for each source and move onto the next. If you need to ensure you only get the 'next available item' for each source observable you can add .pipe(take(1))
to the source observable as you add it to the input array.
Upvotes: 31
Reputation: 38113
Not only does forkJoin
require all input observables to be completed, but it also returns an observable that produces a single value that is an array of the last values produced by the input observables. In other words, it waits until the last input observable completes, and then produces a single value and completes.
In contrast, combineLatest
returns an Observable that produces a new value every time the input observables do, once all input observables have produced at least one value. This means it could have infinite values and may not complete. It also means that the input observables don't have to complete before producing a value.
Upvotes: 224