Check out a free preview of the full Asynchronous Programming in JavaScript (with Rx.js Observables) course
The "Implementing Mouse Move" Lesson is part of the full, Asynchronous Programming in JavaScript (with Rx.js Observables) course featured in this preview video. Here's what you'd learn in this lesson:
Now that Jafar has covered the concatAll() and takeUntil() methods, he revisits the mouse-move code. This demonstrates how user interface events can be reduced to simple collections and handled in a similar way to arrays.
Transcript from the "Implementing Mouse Move" Lesson
[00:00:00]
>> [MUSIC]
[00:00:03]
>> Speaker 1: With your experience with asynchronous programming, how much gain do you see potentially with proper tail calls?
>> Jafar Husain: In asynchronous programming? None, because just to explain briefly, what he's talking about, proper tail calls means if you have a function, and you recursively call that function, and it happens to be the last thing you do inside of that function, which is recursively call it again.
[00:00:29]
What is gonna happen in JavaScript 6 is that instead of growing the stack, which is what happens if you usually, if you call a function inside of itself in recursion, instead of that's not growing, in JavaScript 6, it'll basically turn that into the equivalent of a loop, right?
[00:00:42]
Cuz that's what you're doing. At the bottom of a function, you just call that same function again. It's like it's coming, it's almost like you had a loop. Does that make sense a little bit? And it was hard without an example, but the reason why it totally makes no difference with asynchronous programming is that whenever you do something asynchronous in JavaScript, what happens is that it gets posted on to the event loop.
[00:01:02]
Who here knows what the event loop is? Couple of people? The way JavaScript works is it actually has a list of like a queue of functions to call. And whenever you set, who's used set timeout? Whenever you do a set timeout, what's actually happening under the hood is it takes the function.
[00:01:21]
And what's a timeout is, by the way? It's an API where you handed a callback and a time, and then the JavaScript environment invoke that callback after a certain amount of time has elapsed. What happens under the hood is the JavaScript's got this big list of things to do, and that just takes that function and adds it to the big list of things to do.
[00:01:37]
And eventually, when JavaScript, a certain amount of time goes by, it'll execute that function. And then when that function completes, it just moves to the next step in its list of things to do. Maybe that function that just completes inside of it, and maybe that function just ran, schedule another timeout.
[00:01:53]
And that would post it down here at the bottom of the queue and a list of things for JavaScript to do. My point is that if you're doing anything asynchronous, it always just ends up getting posted on to the list of things to do, and so it's not really tail recurrent.
[00:02:06]
At that point, it's effectively as if you're using tail recurrent, because JavaScript's got this big loop of just going through those things to do, and so it's the equivalent of using tail recursion. My point here is that tail recursion really doesn't have very much to do with asynchronous programming.
[00:02:20]
Because if you are scheduling the next function asynchronously, it's like tail recursion, because it's gonna get put in this big list of things to do, and JavaScript has this big loop where it's going through it. So it's like tail recursion, cuz if you take a recursive function and optimize it into a loop, I'm just repeating the same operation again and again.
[00:02:36]
So I think there may be a slight confusion there. Tail recursion, not really a win for async programming. Yeah?
>> Speaker 1: The next question was, can takeUntil take multiple observables as stop collection or a collection of observables?
>> Jafar Husain: No, actually, I'm not 100% sure. It might actually be able to take multiple collections as stop collections.
[00:02:53]
However, it doesn't matter, because you can always go some source collection .takeUntil some stop collection, .takeUntil another stop collection, .takeUntil another stop collection, .takeUntil another stop collection. So composition solves this problem for us. So anymore questions? Great, so now you guys know everything you need to know to understand how this sample works.
[00:03:17]
At least at a high level, a conceptual level, right? We've got a function, which accepts a DOM object. And then all the mouseDowns, and mouseMoves, and mouseUp here were created using observable.fromEvent. That's the piece of code I've left out of here. Remember that piece of code that adapts from a DOM event to an observable?
[00:03:32]
So the mouseMove, mouseDowns and mouseUps on that DOM element were all created using observable.fromEvent. So we adopted already those mouseMoves into observable objects. So I can go back and quickly remind you guys, right, it was this function. So let's imagine that we took the DOM event, and we actually called fromEvent for a mouseDown and mouseMove and mouseUp, and then we created the observable, we took the observer that came back and actually added it to the DOM event.
[00:04:00]
Now, instead of just talking about it, I'll do it.
>> Jafar Husain: So first things first. We create the mouseDown, mouseMove, and mouseUp observable by adapting them from the DOM elements event name. We add those properties to the element itself, and then that's where mouseDowns, mouseMoves, and mouseUps come from on the DOM element.
[00:05:00]
Does that make sense? Is that clear? Maybe not so much. I can make this even simpler.
>> Jafar Husain: I was trying to get clever there.
>> Jafar Husain: So the first thing we do is we adapt from all of the DOM events on this element. Close one. Still got me here?
[00:06:13]
>> Speaker 3: Yeah.
>> Jafar Husain: So we adapt from all of the mouse events, the DOM events, to an observable, and then we just take the observable that's on there, and we stick it on to the element itself. And now that we've adopted the DOM event, which is this weird adamant listener or movement listener thing, into a single first class object.
[00:06:30]
We can use these map filter function to assemble a new event from three source events. So we're taking mouseDowns mouseMoves and mouseUp, so we're composing them together into mouse drags. And then at the bottom half of the slide, all we're doing is almost a slight syntax that I wanna fix here.
[00:06:47]
And now that I've created a function with multiple lines, I need to add a return.
>> Jafar Husain: The arrow syntax, if using the arrow syntax, and you have to execute multiple lines of code, you need to add a brace, and you need an explicit return method. But if you only have one line of code, you could omit the return method, and you could omit the braces.
[00:07:07]
So now, this is correct. And so what I've done is at the very top of the slide, I've created a function, which when given a DOM element will return an observable of all the mouse drags on that DOM element. And on the bottom half of the slide, I'm consuming the mouse drags now and for reaching over that observable that I've created, and I'm consuming the data, and I'm doing something with it.
[00:07:25]
In this case, moving the image around. Does that make sense?
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops