CombineLatest vs forkJoin in RxJS: Key Differences and Usage
combineLatest emits values whenever any input observable emits, combining the latest values from all inputs. forkJoin waits for all input observables to complete and then emits the last values from each as a single array.Quick Comparison
Here is a quick side-by-side comparison of combineLatest and forkJoin in RxJS.
| Factor | combineLatest | forkJoin |
|---|---|---|
| Emission Timing | Emits on any input emission after all have emitted once | Emits once after all inputs complete |
| Number of Emissions | Multiple emissions over time | Single emission |
| Input Completion | Does not require inputs to complete | Requires all inputs to complete |
| Output | Latest values from all inputs combined | Last values from all inputs as an array |
| Use Case | React to ongoing changes | Wait for all async tasks to finish |
Key Differences
combineLatest listens to multiple observables and emits a new combined value every time any of them emits, but only after each observable has emitted at least once. This means it keeps updating as data changes, making it great for live data streams or UI updates that depend on multiple sources.
In contrast, forkJoin waits for all input observables to complete and then emits a single array containing the last emitted value from each observable. It is useful when you need to wait for several independent async operations to finish before proceeding, like loading multiple data sets once.
Another difference is that combineLatest can emit many times and does not require observables to complete, while forkJoin emits only once and requires all observables to complete successfully.
Code Comparison
This example shows how combineLatest combines two observables emitting numbers at different intervals.
import { combineLatest, interval } from 'rxjs'; import { map, take } from 'rxjs/operators'; const obs1 = interval(1000).pipe(take(3)); // emits 0,1,2 every 1s const obs2 = interval(1500).pipe(take(2)); // emits 0,1 every 1.5s combineLatest([obs1, obs2]) .pipe(map(([val1, val2]) => `combineLatest: ${val1},${val2}`)) .subscribe(console.log);
forkJoin Equivalent
This example shows how forkJoin waits for the same two observables to complete and then emits their last values together.
import { forkJoin, interval } from 'rxjs'; import { take } from 'rxjs/operators'; const obs1 = interval(1000).pipe(take(3)); // emits 0,1,2 every 1s const obs2 = interval(1500).pipe(take(2)); // emits 0,1 every 1.5s forkJoin([obs1, obs2]) .subscribe(([val1, val2]) => console.log(`forkJoin: ${val1},${val2}`));
When to Use Which
Choose combineLatest when you want to react to changes from multiple sources continuously, such as form inputs or live data streams. It updates whenever any input changes after all have emitted once.
Choose forkJoin when you need to wait for several independent asynchronous tasks to complete before proceeding, like fetching multiple API results once. It emits only once with the final results.
Key Takeaways
combineLatest emits updated combined values whenever any input emits after all have emitted once.forkJoin waits for all inputs to complete and emits their last values once.combineLatest for ongoing reactive updates, forkJoin for waiting on multiple async completions.combineLatest can emit multiple times; forkJoin emits only once.forkJoin requires all observables to complete, combineLatest does not.