Control the Output of Values with RxJS Operator withLatestFrom

André Staltz
InstructorAndré Staltz
Share this video with your friends

Social Share Links

Send Tweet

Operator combineLatest is not the only AND-style combinator. In this lesson we will explore withLatestFrom, another AND-style combination operator, and how it works essentially as map() operator, with some combination properties.

🚨 Since we are importing interval from RxJS, we don't need to preface our Observables with Rx.Observable. You can no longer .{operator}, you need to .pipe({operator}) instead. To link together multiple Observables and Operators, the method is a bit different. You call zip first, then list your Observables, your functions, then pipe your Operators.

[00:00] There are other combination operators that work like CombineLatest. One of them is withLatestFrom, and it's curious that it's also an and style combination operator. CombineLatest is still the most common and most important and combinator, but it's not the only one. WithLatestFrom is similar because it also takes a function that works on those values.

[00:24] Whenever you have a combination operator that takes a function like this, it means that it's an and style combinator. Let's see how withLatestFrom works and why is it useful. Sometimes you have an observable, which you want to simply map. Let's say this observable would be an observable of characters like this saying, "Hello."

[00:46] Suppose that this is being emitted by some text input field, for instance, and then you want to map that to just the upper case version of those characters. You can do this with a map, but let's say now that we want to conditionally map. Sometimes, it's lower case, sometimes it's upper case depending on another observable.

[01:10] Let's say that we have this other observable bar, which admits the number zero and one. This is bar. What we want to do is we want to map each of these characters to upper case only if the latest value from bar was one. We want to map it to lower case if the latest value from bar was zero. In this case here, since the latest value from bar is zero, I want to map this to lower case.

[01:36] Here, the latest value from bar is zero, I want to map it to lower case. Here, the latest value from bar was one, I want to map it to upper case. Same thing again, I want to map it to upper case. Finally here, I want to get the latest value from bar, It's zero, and I want to map it to lower case.

[01:55] This is still a combination. We're combining these two observables, but essentially we're still just mapping foo to something. That's what withLatest does. You can actually think of it as map withLatestFrom. The map is sort of implicit, but it's called withLatestFrom and you provided a function of characters and numbers, characters come from foo and numbers come from bar.

[02:22] We map that to, well, it depends. If the number is one, we want to map the character to its upper case version. Otherwise, we want to map that character to its lower case version. This is what withLatestFrom will do.

[02:41] Let's try using it in practice here, and we hit that function to combine the values. Let's run this, and we see there a lower case "H," lower case "E-L-L-O," just like we had outlined here. We use withLatestFrom to map an observable, foo, to another observable, but using the latest value from some other observables.

[03:12] That is why there is no static version of the withLatestFrom operator. That's because foo here is somehow special. It's different. It's assuming a different responsibility than bar is because essentially it's not like CombineLatest. If we would use CombineLatest, then when one is emitted on bar, it would be combined with latest value from "H" and that would make upper case "H," but that's not what we want.

[03:40] We want basically this to be a mapping of that observable, just using some secondary information from other observables. The main observable is foo, that's what we want to map. That's why foo here is special because it's the main observable and we just want to use secondary information from other observables.