
JavaScript: The Hard Parts Introducing Asynchronous JavaScript
This course has been updated! We now recommend you take the JavaScript: The Hard Parts, v2 course.
Transcript from the "Introducing Asynchronous JavaScript" Lesson
[00:00:00]
>> Will Sentance: All right, so we achieved a lot yesterday, we achieved a lot. Principles of JavaScript, the core fundamental pieces, that our synchronicity executing JavaScript does. Then higher order functions, then our other type of higher order functions, the ones that return functions. Remember, any function that takes in a function or returns a function is a higher-order function.
[00:00:26] The return functions was what gave us closures, or what we like to call the backpack, or what we like to call the persistent lexical scope reference. And that was very impressive by all of you. I was very, very excited to see multiple people in this room complete some of those tough closure challenges afterwards, all the way into those ones that take in a function, wrap it, and then return out the wrap function that behaves the same way as the input function, but with special nuances.
[00:01:03] If you'd known that was how it worked, maybe that would have made it easy. But those are really tough challenges, and I was really impressed to see so many of you complete those. All right, but now, today we move on to a land of JavaScript that introduces pieces that we've already said, we had all of the features of JavaScript.
[00:01:24] But part four and five are gonna introduce us to two additional aspects of JavaScript that are gonna complement what we already have. So we said we already have our memory thread doing the code line by line, our core stack keeping track of these memories and threads which is together, or memory and thread, which is together known as an execution context.
[00:01:46] So these new parts are gonna compliment those core features. The first one is asynchronous JavaScript. Asynchronicity, backbone of modern web development in JavaScript. JavaScript is single threaded, that means doing one line of code at a time. Not when I start running a function, I can continue on with my code, for example, else outside the function.
[00:02:15] I can't do two things at the same time. At asynchronous, each line, if it's displayed as the next line, it's gonna run. So we view in the world of JavaScript, in the world of the Java engine, yeah. So then we have something that's gonna happen, some issue might arise.
[00:02:32] What if we need to wait sometime before we can execute certain portions of code? What if we have a block of code that we know we're going to want to execute maybe when we get some fresh data from a request to a server for our new tweets or whatever it might be?
[00:02:52] Or maybe for a timer to complete, and then we want to execute this code. So we announce this cuz we wanna have it not actually run, we've got to do some waiting, we wanna wait until we run that code. So for example, suppose it's the functionality that says, take the data you just got back from the APIs, Spotify's API or whatever, or Twitter's API, take that data.
[00:03:14] You've had to wait for it, but now it's come back. Now take that data, it could be five tweets, and display it on the webpage. We're gonna do that waiting, we announced the fact that we've gotta wait for that to happen. We've got a conundrum, we wanna delay that running the code, there's no point in running the functionality saying, display my data, display my tweets, until the tweets are there.
[00:03:38] Let's be really clear, we can't display tweets if the data hasn't arrived yet, okay? So we've got attention between delaying that code executing, the bit for displaying the tweets, but not wanting to block the thread. Remember, we said we're doing one thing at a time and in order.
[00:03:57] So if the next thing is display tweets, we aren't doing the line after that until the data displays the tweet. If it were there and we can display the tweets. So our thread one thing at a time and in order. So if the next thing is take the data, display the data on the page, and we've had to wait 400 milliseconds for that data to come back, nothing is happening, no code's happening afterwards.
[00:04:21] We've got a conundrum, we can see this is a conundrum. What do we do?
>> Will Sentance: Do not panic yet. Let's just see two examples to see just how much of a confusing conundrum this is. Our existing world of JavaScript does not our existing world of JavaScript may not have a solution for this situation.
[00:04:42] Our three core features may not have a solution for this scenario. So let's look at the example, in what order will our console logs appear? So we're defining a function printHello, inside of which we have a console.log("Hello"). Then we're calling this setTimeout built-in JavaScript method, and it's gonna pass in that printHello functionality.
[00:05:05] And a value of 1000 milliseconds that's going to, in theory, delay the running of that printHello function for 1000 milliseconds. And then this additional console.log("Me first!"). Okay, Katie, what order are these console.logs gonna actually run in, do you think?
>> Katie: I think is gonna do Hello first and then Me first?
[00:05:28]
>> Will Sentance: Well, that might make sense, right? Because we've got stuff, we've got a single threat in JavaScript. Thank you, Katie, for saying that, that's very good, it’s raised our attention. [SOUND] Maybe, we've got a single threat in JavaScript, so for saying wait 1000 milliseconds to run to printHello function, in which we're going to print hello, console.log("Hello").
[00:05:50] Well, we should expect that to come first before Me first. Who has a different opinion on how this is gonna work? Yeah, go ahead, Lindsey.
>> Lindsey: I think it will read the first function, setTimeout.
>> Will Sentance: But Lindsey, this is impossible. No, it's not, obviously, but this is impossible because clearly it says recalling setTimeout and if we are inside of setTimeout doing that printing, it's being passed into setTimeout, right?
[00:06:17] Then it must be waiting inside that function's execution context before going back to global and encountering Me first. It must be inside a setTimeout, new execution context inside of which we then wait 1000 milliseconds, in theory, and then printHello, and then out we come at setTimeout, and go out to global and hit console.log.
[00:06:39]
>> Will Sentance: No, it doesn't do that for some reason. For some reason, actually, Lindsey's spot on, Me first happens first, and at least 1000 milliseconds later Hello happens. It's not blocking, no blocking. And the other reason the other thing is called a, how was it called? Something bang.
>> class: Interabang.
[00:07:01]
>> Will Sentance: Interabang, I was reading the Wikipedia page about it, exactly. There you go, thank you, man. It's old, 1923 it was around. [SOUND] There we go. So then all right, so we're saying 1000 milliseconds, fine, printHello goes off, and somehow is run 1000 milliseconds later. Our JavaScript system is not explaining this, in my opinion, yet.
[00:07:23] What about this one? In what order do our console logs appear here, Lindsey? Declare printHello, Hello, setTimeout, printHello, pass in zero millisecond wait this time, and then this console.log("Me first!"). Lindsey, what do you think is gonna be the order here? Actually, let's give Katie a chance. What do you think, Katie, is gonna be the order here?
[00:07:46]
>> Now I think it's gonna do Hello and then Me first.
>> Will Sentance: That's double down on it, Katie. Good shout.
>> class: [LAUGH]
>> Will Sentance: What do you think, Lindsey?
>> Lindsey: I think the same.
>> Will Sentance: Even in this situation, printHello is gonna come after. Man, do we think now that our current system that was explaining JavaScript running is sufficient?
[00:08:09] It does not explain the situation, does it? All right, I've got this expression. [LAUGH] Do you think it's sufficient? I don't know.
>> class: [LAUGH]
>> Will Sentance: Our previous model of JavaScript execution is insufficient. There you go, there's your answer. We need to introduce three new components of our platform, or thinking about JavaScript.
[00:08:26] Top three, we already have thread of execution, memory/variable environments, and call stack that tracked those execution contexts, that are, of course. Remember, execution context is just, we're doing the code line by line, in the function or globally, known as a thread of execution. Threading down, executing each line.
[00:08:46] And then the memory where you store stuff that you encounter as you thread through, and that's known as execution context. And the call stack tracks those execution contexts. We need to add three new pieces, web browser built-in functionality. These are not APIs the way you think of when you go to Twitter's API or Google Maps' API.
[00:09:07] Remember, API just means there is some functionality or data out there that is not in my application, but I can access it and interact with it in a clean, predictable manner, even though it may be written in a different language, a different server, a different owner of the data, whatever, I can interface.
[00:09:25] That's what API, the I stands for, I can interface with that functionality. And it turns out we've got to look at does our web browser, Chrome, Firefox, etc., what functionality do they give us outside of pure JavaScript that we can interface with? Those of our web browser APIs, our web browser functionality or features, that we in JavaScript can interface with.
[00:09:52] Also note these are known as background threads. We gotta add the callback, or message, or task queue, and we have to add the event loop. Event loop and callback, message, task queue, fascinating. We're obviously gonna look at them. They're not as, well, they're vital for this, but it turns out that we're gonna start off with our web browser APIs.