Check out a free preview of the full Advanced Asynchronous JavaScript course

The "Helper Functions" Lesson is part of the full, Advanced Asynchronous JavaScript course featured in this preview video. Here's what you'd learn in this lesson:

After reviewing the problem statement, JavaScript continues to examine helper functions including dinstctUntilChanged() and scan().


Transcript from the "Helper Functions" Lesson

>> Jafar Husain: Let's go back, and let's remind ourselves what the problem was, right? We have animations allowed, we have this two dimensional tasks, and we want to go down to this nice stream of true false values. animationsAllowed. And it switches to false as soon as you begin a new task.

And it switches back to true as soon as all of the outstanding tasks are done, and then it switches back to false as soon as a new task begins and so on and so on and so on. That make sense? So I was showing you guys some helper functions, and we just learned one which was concat.

Right? And you can just take as many, if you have two observables in your hot little hands, you can just put them together like two strings. And distinctUntilChanged, can anybody figure out how that works? Can anybody describe verbally how that works?
>> Student1: It looks like it is waiting for the value to change, so if it gets a new value it'll pass that on, but then until it hits something else it won't pass those values on.

>> Jafar Husain: Right. And we'll see why that comes in handy later. And scan, scan's one of my favorites. Does anybody remember reduce? How reduce works? So if I take this,
>> Jafar Husain: and I do this,
>> Jafar Husain: What am I gonna get?
>> Student2: Six.
>> Jafar Husain: Six, yeah, absolutely right. In our little modified version of reduce that we use in JavaScript, yes in our modified version of reduce that we use in the previous class you actually get an array of six.

Here you don't get six. I made a mistake there I'm sorry, you actually get all the intermediary values. So scan is different than reduce because instead of just giving you the last value it gives you all the intermediary values In the computation. So basically, every value that was returned by this function ever.

Does that make sense? Do we feel like we got a good handle on reduce? Let's go over it real quick. The way reduce works is it takes the first value, and that becomes acc. Takes the second value and that becomes current, and runs them through a function that combines them.

And what do we gout when we take one and two and add them together? We get three, and whatever comes out of that function becomes acc the next time. And so we see this thing where the value comes out of the function and then gets pumped back into the function, right?

And then we take the next value off, which is three, and three plus three is six, and because the stream is now ended, we get six. The only difference with scan is that it gives us every intermediary value it passes as acc. So we get one, three, and six.

Does that make sense? So we're going to use scan. Scan's super helpful. Oops, I should have written scan there. Scan's super helpful when you want to count things or keep track of things, right? Imagine a progressively better standard deviation over like a stalk string. You'd use scan in general when you are working with an infinite string.

Why wouldn't I use reduce for an infinite string?
>> Student3: It'll never finish?
>> Jafar Husain: It will never finish right? Because reduced only gives you a value when it's gone through the entire stream. And so if I try and reduce Netflix's stock price, I hope it'll never end, right? So fingers crossed.

But if I wanted to get a gradually better standard deviation over Netflix's stock price I could use scan, and then I'm just gonna get a gradually better computation over time. So with these three functions in mind, let's see if we can now, and the ones that you learned in the previous class, things like switch map, concat all, these things, we're gonna now see if we can tackle animations allowed.

>> Student4: I have a quick question.
>> Jafar Husain: Yeah.
>> Student4: In RX is there an operator that works like concat, but it doesn't wait for the one to finish before the other one?
>> Jafar Husain: Great question. Awesome question. Yes, there is, and it is merge.
>> Student4: Okay.
>> Jafar Husain: And what we would get here, I'm gonna actually get the smallest one.

To make things simpler.
>> Jafar Husain: Make sense?
>> Jafar Husain: Right? Now concat and merge and the cousins of the flattening operators that we learned in the previous class. Does everybody remember the flattening operators? There are three of them, and they're really powerful because we can solve most concurrency problems with these three flattening operators.

The reason why we call them flattening operators is they work on two dimensional observables like the tasks observable that we're working with in the animationsAllowed example. So they are.
>> Jafar Husain: I'm gonna do this over here because Powerpoint coding is annoying, and we're gonna make ourselves a two-dimensional observable.

>> Jafar Husain: So given this two-dimensional observable, there are three operators. Can anybody tell me what they are for flattening two-dimensional observables? There's more, but these are the most common.
>> Student4: So they accept the two-dimensional and then just flatten it slight?
>> Jafar Husain: Flatten it down to one.
>> Student5: flatMap is one of them.

>> Jafar Husain: flatMap, yeah. Actually, flatMap's-
>> Student4: mergeMap?
>> Jafar Husain: mergeMap, absolutely. They're slightly modified in the sense that they're basically flattening the result of a map operation. So I'm talking about just the basic one that just takes the two-dimensional, observable and flattens it down. You have one, which is merge.

You have one, which is, anyone want to yell it out?
>> Student1: Concat.
>> Jafar Husain: Concat. And then finally you have the most common operator used in the UIs. switchLatest. This is definitely worth reviewing. So anybody wanna guess what- Sorry this is called mergeAll, concatAll. Anyone wanna guess what mergeAll's gonna produce here, based on what merge produced a second ago?

>> Student1: Five, five, three, five, two, five.
>> Jafar Husain: Five, five, three, five, two, five. So merge is a lot like four, so let's imagine there's some accident on the freeway and three of four lanes are all used up. What happens, at least in a civil society? What do we do?

Let's imagine each of these as lanes of traffic, right? And you're all merging down to one.
>> Student1: Trade off on which goes next.
>> Jafar Husain: Well, basically whoever gets there first, so that's one strategy if you're bumper to bumper. But whoever gets there first, in general, right, can make it through.

So that's why we merge looks like this. So basically as soon as data comes, you subscribe to all of the observables at the same time. So you remember what we did with concat, the first thing we did that was wrong, which was we immediately subscribed to all the observables?

That's not wrong in merge, that's exactly what you do. You subscribe to all those observables at the same time. And then whenever any of them gives you data, you just plummet through as soon as you get data from any of the observables. So that's why we see that when they flatten it down, they're all there in one stream in the order on which the data arrives.

Anyone wanna take a guess as to what concatALL does though? Yeah?
>> Student4: It's gonna return the first observable five, three, two, and then it's gonna return, once that's done it's gonna start on the second one, it's gonna return five, five, and then once that's done it's gonna return the third-

>> Jafar Husain: Yes.
>> Student4: Which is five.
>> Jafar Husain: ConcatAll is like the cousin of concat. Remember concat just takes two observables or n observables and subscribes to one, and when one completes it subscribes to the other one and so on and so forth. If you have a two-dimensional observable what concatAll does is as soon as it gets an inner observable it subscribes to it, and if it gets another inner observable while it's still subscribed to the previous one, it doesn't subscribe to it it just puts it into an array.

And then when this one completes, then and only then, does it subscribe to this one. And that's why, incidentally, we see this little time elongation here. Notice that these three dots don't even start because this is a cold observable. It's not gonna even start producing the data or doing the work until we call subscribe on it.

And so concatAll has the effect of lengthening the observable when we flatten it down. Does that make sense? So it's as if we took every inner observable and we just put it near the end of each other. And this one is, by far, the most common operator used in UIs, switchLatest.

>> Jafar Husain: Anybody wanna tell me what you think this is gonna output?
>> Student4: Give yellow fives?
>> Jafar Husain: All fives. As a matter of fact it will. I keep forgetting to uninstall that thing. It will give you five, you know, I'm not sure, you might actually be right I'm trying to figure it out.

I think you are right. Well done, sir. I think it will give you all fives. Yes. Isn't that weird? Why does it give you that?
>> Student1: Because when a new observable comes along even though it's still going on with the-
>> Jafar Husain: You know what, I made a mistake.

Sorry to interrupt you. One less five here. No, no, sorry never mind I was right. Go ahead you were saying.
>> Student1: So whenever a new data stream comes in or whenever a new observable comes in it'll stop at whatever one it's on. It only cares about updated data.

>> Jafar Husain: And how's it gonna stop? Under the hood what-
>> Student1: Well I mean, it's just gonna switch over to-
>> Jafar Husain: Switch over? And if we were to go over and implement switchLatest right now, and this is a threat. So you can tell me the answer or I'll have to go and format it, nobody wants that.

What's it gonna do under the hood to that observable in order to stop getting data from it. VS, which latest operator. So it gets this int or observable, you're 100% right, it subscribes to it. And then when another inner observable comes along, how's it gonna make sure it doesn't get any data from that previous one?

What's gonna stop it?
>> Student1: [CROSSTALK] and subscribe.
>> Jafar Husain: Subscribe, absolutely, right?
>> Student4: Wouldn't there be four fives then?
>> Jafar Husain: Good question, why is there not four fives?
>> Student5: Because the second observable started being subscribed to before the first was able to [CROSSTALK].
>> Jafar Husain: Right, we don't switch when we get the first piece of data, we switch when we get a new observable, and so we never got an opportunity to get this five because right here, another observable came along.

Good call man. So, now why is switchLatest the most commonly used operator on UIs? Sorry?
>> Student4: That's how the user interfaces work?
>> Jafar Husain: Yeah, the users change their mind and most of the time, you don't care about the last thing they told you to do. If the new thing they told you to do supersedes that, right?

We see it all the time in UIs. I open up a forum. You start loading data, and I show a loading bar. In the meantime the user hits Back. Do I want to get the results of the network request anymore? Nope. In fact, if I didn't guard against getting the result of that network request, bad stuff might really happen, right?

Somebody might go back and then we might try and load the data, the DOM elements from the previous form. It is very, very important to avoid this race condition in UIs. And so it is a good heuristic if you're wondering what flattening operator to use, right, until you really got the solid fundamentals, a good first guess is switchLatest if you're on a UI, right?

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