withLatestFrom
The
withLatestFrom
operator is your best friend when you have one main observable whose emissions depend on the latest values from one or more other observables. Think of it as a one-way data flow, where the primary observable takes the lead and other observables chime in with their most recent values.A classic example to remember
withLatestFrom
is a chat application that needs to send a message with a user's current location. The message sending event (main observable) combines with the latest location data (another observable) to form the final message object.Keep in mind that
withLatestFrom
only emits a value when the main observable emits, and after each additional observable has emitted at least once. This can catch you off guard, as you might not see any output or errors while one of the observables isn't behaving as expected, or a subscription is delayed.If you need to combine values from multiple observables that emit more than once and are interdependent, consider using
combineLatest
instead. And for scenarios where observables emit only once or you just need their last values, forkJoin
might be a more suitable choice.Example 1: Latest value from quicker second source
// RxJS v6+
import { withLatestFrom, map } from 'rxjs/operators';
import { interval } from 'rxjs';
//emit every 5s
const source = interval(5000);
//emit every 1s
const secondSource = interval(1000);
const example = source.pipe(
withLatestFrom(secondSource),
map(([first, second]) => {
return `First Source (5s): ${first} Second Source (1s): ${second}`;
})
);
/*
"First Source (5s): 0 Second Source (1s): 4"
"First Source (5s): 1 Second Source (1s): 9"
"First Source (5s): 2 Second Source (1s): 14"
...
*/
const subscribe = example.subscribe(val => console.log(val));
Example 2: Slower second source
// RxJS v6+
import { withLatestFrom, map } from 'rxjs/operators';
import { interval } from 'rxjs';
//emit every 5s
const source = interval(5000);
//emit every 1s
const secondSource = interval(1000);
//withLatestFrom slower than source
const example = secondSource.pipe(
//both sources must emit at least 1 value (5s) before emitting
withLatestFrom(source),
map(([first, second]) => {
return `Source (1s): ${first} Latest From (5s): ${second}`;
})
);
/*
"Source (1s): 4 Latest From (5s): 0"
"Source (1s): 5 Latest From (5s): 0"
"Source (1s): 6 Latest From (5s): 0"
...
*/
const subscribe = example.subscribe(val => console.log(val));
Last modified 5mo ago