Rx.js Fundamentals

Higher Order Observables

Steve Kinney

Steve Kinney

Rx.js Fundamentals

Check out a free preview of the full Rx.js Fundamentals course

The "Higher Order Observables" Lesson is part of the full, Rx.js Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Steve discusses higher-order Observables, returning Observables, and mapping operators, A student's question regarding if some of the operators could be used to implement an undo operation in the case of a UI update rollback is also covered in this segment.


Transcript from the "Higher Order Observables" Lesson

>> So, we're talking a little bit about what's called kind of higher order observables. Higher order observables are if you think about higher order components in react or name, your framework of choice, it is simply a component that renders another component. And in most programming everything is easy.

Until you get to the point where you are when you're like mapping over an array, fine. I can do that, anyone can do that. Iterate over an array. What happens that array contains an array. Well, now you've got to recursively go into that array, do everything in that array, so on and so forth, right?

And so, you can either use recursion and, for instance JavaScript. These days, right, has a built in like flat map. The idea of like take this multi dimensional array and just make it one regular array of all the values. That is also super useful in terms of working with observables.

Right, okay, they have clicked great but that click like maybe what you wanna map it into a promise. Well, a promise in this case will also become an observable. So, now you've got an observable floating down your observable stream, right? What really, you don't want the observable in that case you want the value, Mark?

>> Some of these operators be used to implement an undo operation in case an optimistic UI update should roll back.
>> I mean, you could right? Like if you think about scan, you can take care of all of the state, right. There's also, you have the ability to kind of replay in some cases.

I think with scan is probably the best way to do it, right? Because for a lot of these, we'll see the ability to like switch between pieces, but keeping track of that state and taking the different events that kind of go through and be able to manage all that will let you kind of adjust that as you go along.

With most things, everything is easy until you have things that appear in other things. So for instance, this would be problematic. Remember when we had that original delay in the notification we slammed on a bunch of times. And yeah, we waited two seconds and then we got all of them, right.

If you wanted to theoretically, have a observable that then we'll use of, to then delay it a certain number of milliseconds. Well, now you have an observable in your observable. And so, you'll get is when you subscribe to example, you're gonna get an observable cuz that's what you return from your map, right?

Is that what you wanted, [LAUGH] yeah, sometimes we don't get what we want we get what JavaScript tells us we get we like it. So, that's what we'll get in this case and like a more common example is the button got clicked or here was a string, or here was an array of things I want to use from fetch to get observables.

Again, now I have a stream of observables that have a stream. What I really wanna do if I can take two observables from the top level and merge them together, I should be able to take observables in my observables and flatten them into the main observable like the the sacred timeline, if you will.

And merge my timelines into the main timeline in this case, and if you're thinking I should be able to do that, good news, good, you're thinking correctly. So, one strategy for doing this there's an operator called merge all. So, merge all or basically take all of the kind of child observables in your stream, and merge them together just like when we merge the first and the second observables before, right?

Now, this is common enough that there's also a fun helper called merge map. You wanna take a lucky guess what that does?
>> Merges maps together?
>> Yeah, it's like flat map, right? It maps and then it merges them all together. So, a lot of times you will see that happen way more frequently than you will map and then merge.

You'll usually just merge map and save yourself a whole, I guess 9 characters or 10 characters of code. Guess the comma, so 11 characters of code. You can merge map and you can do it all in one pass. And a lot of the rules that we saw before apply as well for concat, so concat will do the same thing.

It will do what concat did previously, you'll map over all these items. There'll become nested observables, plays with the first one, then play through the second one, then play through the third one, right or so on and so forth, right? It all depends like the unique problem that you're trying to solve, if you don't have opinions, merge is your best choice.

You're like, whatever, someone admitted, I wanna do with that value. But there are times where you want to coordinate and orchestrate the different asynchronous events and that's where concat and two other fun ones are gonna show up. So, the more useful ones even, merge map super useful concat map, sometimes useful, like when you need it in particular, switch map and exhaust map are like cousins of the bounce and throttle, right.

And they kinda again work the opposite of each other. Switch map says, drop whatever you're doing, something else has omitted. I don't even care what I was doing previously. Forget it. I don't wanna know anymore. Right, I wanna do the new thing. Exhaust map is a little more stressed out.

It's like, I'm very busy doing this thing, not doing other things. I'm done with this thing. And then, if anything else is there to be done, I will go do it. The interesting part is, like very similar to debounce and throttle switch map will simply cancel, stop no more, it'll move on to the new hotness every time, exhaust map will just ignore things until it's done, right?

When it's done that if something else wants to emit, it'll switch over to that one, but it will finish what it has done previously. Now, we've talked a little bit about autocomplete along the way here. So for instance, like, cool, maybe they stopped typing for 300 milliseconds or debounce time has fired.

We're ready to make another request. I don't care. You're halfway through an API request, request is taking too long. We're done. They're no longer searching for that. I don't wanna know when it comes back. I'm uninterested, right, we have new things we're searching for. And when that request comes back, whether it's before or after the other one, right, if you have like a like slow internet connection you like, the first request might come back after the second one.

You don't wanna update the UI for the thing they're done searching for, you wanna update the UI for the thing they most recently searched for. Exhaust map will be like, we're loading things right now. I know they're rage clicking that button. We're loading things right now. [LAUGH] We're doing it, right?

This is maybe for data that's not gonna change too much. You don't need to fire off a bunch of different requests, like this request will get them the data they want. Just don't fire off new requests until this comes back and then they wanna search again. Fine, right?

This could be a field where it's like we are loading the previous thing, cool. There's just a few more that we won't play with too much, but I just wanna like make you aware of their existence. Remember, we saw a fork join before it gave you the last value of all the observables combined latest all will simply as long as all of them have emitted, it will wait until each and every one of them emits.

Once they have all emitted you will get an array of all the values, right? So, if there's still one you're waiting on you don't get anything. But once everyone has done something you'll get an array of all the things that happened. If you are impatient and want this ASAP you can use a start with to kind of kick off each one of them and then you'll get an array each and every time any of them admit, right.

So, this can be useful if you're building a UI like, hey, I'm making a pixel painter, right? I wanna know where their mouse is. I wanna know what color right these are all things that can change, right? Give me the latest of all of these things depending on what we're doing, right?

And then, combine latest with just a way to kind of, I want to rely on this other observable, give me the last one of that every time. So, the question is if you use exhaust map and things happen while you're doing the first thing are those things backed up into a queue?

They're completely ignored, thay're dropped, right? We don't like we're busy, we're not doing those things afterwards they could rage clicked to their heart's content, we're not dealing with it, we're not doing it. We're finishing what we did in this case and we'll go ahead and when we're done, we'll do the next thing, right?

Like if an autosave is in progress you might wanna let that autosave go through or maybe you wanna switch it to the new one, a lot of this will depend on the exact type of interaction you're trying to develop. But the idea is that you have these options you have the option to kinda finish what you started.

You have the option to drop what you're doing and do the new thing or merge, hey, I don't care like things happen like they can start and stop that timer, I'm unconcerned, I don't really care in this case.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now