JavaScript: The Hard Parts, v2

Callback Queue & Event Loop

Will Sentance

Will Sentance

Codesmith
JavaScript: The Hard Parts, v2

Check out a free preview of the full JavaScript: The Hard Parts, v2 course

The "Callback Queue & Event Loop" Lesson is part of the full, JavaScript: The Hard Parts, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Will defines the concept of a callback queue, then diagrams an example that demonstrates the functionality of the event loop, which ties the call stack and callback queue together.

Preview
Close

Transcript from the "Callback Queue & Event Loop" Lesson

[00:00:00]
>> Will Sentance: We have our printHello. We have our blockFor1Sec. We're going to call this setTimeout. Is setTimeout doing anything in JavaScript of interest, Kayla?
>> off screen female: No.
>> Will Sentance: No, nothing in JavaScript. Then we're gonna call out blockFor1Sec. And then we're gonna, let's see, well maybe we're not gonna call out blockFor1Sec for next.

[00:00:17]
Who knows, we shall see. So, there's our global memory. Line one, Kayla, what are we up to?
>> off screen female: We're defining the printHello function.
>> Will Sentance: Very nice, we're defining the printHello function. Excellent, next line over to Jeff.
>> off screen male: We define a function, blockFor1Second.
>> Will Sentance: blockFor1Sec, exactly, there it is.

[00:00:44]
We don't know how it's, I mean, we know how it's gonna work. We're not writing its code out, but if we ran it, you would run some sort of for loop, or something like that. Definitely not a timer, just be clear. It's an easy trap to fall into.

[00:00:55]
Now, things get interesting. Now, we hit our first facade function for a feature of the web browser, setTimeout. And we're going to invite Ethan, no, no, no [LAUGH] Ethan's line was excellent. We're not gonna put even through that again. printHello, and this time is 0. I mean, the second wait.

[00:01:22]
Okay, I should give them to you from there. setTimeout, do we have anything in JavaScript of any interest? No, what instead is in a command to which part of our-
>> off screen male: It's gonna send a message to the web browser?
>> Will Sentance: Very nicely put, it's gonna trigger in the web browser, the switching on of the timer, of a timer.

[00:01:48]
And what information does it need here, Mark, to be an effective timer?
>> off screen male: The actual time.
>> Will Sentance: Yeah, right? 0 milliseconds, and also, Ethan?
>> off screen male: The function definition printHello?
>> Will Sentance: Yeah, that's what we're gonna run on the completion of the timer. Perfect, very nice. And this is all happening at roughly what time?

[00:02:09]
Maybe 0 milliseconds or something like that, roughly 0 milliseconds, there it is. Now, we need everything below here to be our Web Browser. So there it is, Web Browser features.
>> Will Sentance: Web Browser features Timer in the web browser. So we'd say the feature we're gonna use is the Timer.

[00:02:46]
Turn on a timer, set its time to completion to be 0 milliseconds. On its completion, just remind us, again, Matt, on completion. What do we want to have happen?
>> off screen male: You want it to run the printHello.
>> Will Sentance: Perfect, run the printHello function. So we're going to pass into the web browser a reference, a link back to the function we want to run in JavaScript.

[00:03:09]
But think of it as being the function is now, so just be outside of JavaScript or at least it's sitting there ready, hopefully to be run back inside JavaScript at some point. Now question, I wanna turn to Kayla on this one. Kayla, is at 0 milliseconds, is our 0 millisecond timer complete?

[00:03:34]
>> off screen female: No.
>> Will Sentance: 0 minute timer at 0 milliseconds, what do you think? Is that kinda,
>> Will Sentance: Is it complete? How would it take any longer than 0 milliseconds? Todd, you didn't complete.
>> off screen male: Okay, so my question would be, is that 0 milliseconds the same as that 0 milliseconds?

[00:03:56]
>> Will Sentance: Yeah, 0 milliseconds, our 0 millisecond timer is complete, people. There you go, good job. 0 milliseconds, our 0 millisecond timer is definitely complete, right? I don't know how many more than milliseconds it would take. It's like, yeah, 0 millisecond is a complete timer. Because crazily, it's like done.

[00:04:14]
It's done, it's all it is. It's a 0 millisecond timer. So I presume printHello gets grabbed and put on to the,
>> Will Sentance: Call Stack.
>> Will Sentance: What do we think people?
>> Will Sentance: And yet, it is complete and so it's time for the function to go onto the Call Stack.

[00:04:40]
>> Will Sentance: I'm making sure I stand on my best foot. Turner told me this is my best angle. It is complete, so I guess you get, folk, there's another part to the puzzle that we need to know about. And I'm not gonna beat around the bush on it. I'm gonna talk about it right now, which is this.

[00:04:58]
It's called, it's a queue. I heard the word said from a few people when you were talking about it. It's a queue of, what do we call these? What do we call baby functions that get passed into other functions? Little functions that get passed as inputs into other functions.

[00:05:13]
>> off screen male: Callback.
>> Will Sentance: Callback, so it's a queue of callbacks. A callback queue. Do not by the way confuse it, or do not confuse these callbacks with the ones we saw yesterday where they run inside of the higher order function. No, no, no, this one is grabbed and thrown right out of.

[00:05:36]
This is just a command. At no point is printHello run inside of setTimeout. They just grabbed that function, set it and threw into the timer into the web browser and it's stored here. Or at least a link to where it was originally defined is store there. At this moment, at 0 milliseconds, printHello ain't going on the Call Stack directly.

[00:05:56]
It's gonna have to queue itself up here into the callback queue it goes, at 0 milliseconds, ready to run. There's our friend printHello, and it's gonna sit in the callback queue ready to run.
>> Will Sentance: But it's still ready so I guess now, as we complete the setTimeout, we're gonna pile on, accelerated on to our next line which, Dan, at 1 millisecond.

[00:06:31]
>> off screen male: We're going to call blockFor1Sec?
>> Will Sentance: But, little printHello is sitting there waiting. Who thinks Dan's right? Dan is spot on. We are gonna call blockFor1Sec. Most interesting. blockFor1Sec. Brand new execution context. We're not gonna sort of go through its details. But, I'm adding so much detail for it, brand new execution context.

[00:07:00]
There it is. And our thread of execution is gonna weave in. It's going on the call stack. blockFor1Sec, we go into it at 1 millisecond. It's gonna take 1,000 milliseconds inside.
>> Will Sentance: Now we have the question. At any moment, do we think, while we are in blockFor1Sec, it's doing for loop, lots and lots of iteration.

[00:07:32]
At any moment there, do we think printHello is allowed out of that queue to be run on the call stack? It's not. But my goodness, it's been waiting for 0 milliseconds. We're gonna come out of blockFor1Sec at 1001 milliseconds. And our little printHello is gonna say, okay, finally, you finish your function.

[00:07:59]
You popped it off the call stack, let's pop it off the call stack. Okay, finally, I'm allowed out. And it's been waiting there quite eagerly, very excited, say, I wanna come out. I wanna [LAUGH] be out of the queue into the call stack. And finally at 1001 milliseconds, what do we think happens?

[00:08:22]
Is it allowed out?
>> off screen male: Yes.
>> Will Sentance: No, it's still not allowed out. [LAUGH]
>> [LAUGH]
>> Will Sentance: Instead, our poor little printHello is gonna sit there and what's gonna run instead, Todd?
>> off screen male: The console.log me first.
>> Will Sentance: console.log me first, exactly right. Our console.log me first. There it is into our console will be logged at 1,001 milliseconds.

[00:08:50]
Me first. Exactly right. My goodness. Now at 1002 milliseconds, you're all nervous to even say it. At 1002 milliseconds, now surely, okay, that's my voice, I'll do Mile's yes voice. Now, Brayden, what do you think is gonna be allowed to run and be put on the call stack?

[00:09:15]
>> off screen male: printHello.
>> Will Sentance: printHello, exactly right. At 1002 milliseconds, printHello grabbed out of the queue, put on the call stack, and there it is, printHello is executed at 1,002 milliseconds. Therefore, Brayden, we see in our console, what?
>> off screen male: Hello.
>> Will Sentance: Hello, exactly. My god, there we go. So folk, can you try and ascertain.

[00:09:51]
>> Will Sentance: Yes, can you try and ascertain what is our fundamental, that was my low point trying to use a word I just learned. Can we try and ascertain what was our rule for when a function in the queue that's being thrown out by using one of these facade functions, out into the web browser.

[00:10:14]
setTimeout ain't really doing anything in JavaScript. Instead, it's just grabbing that function, [SOUND], throwing it out here. What is the rule by which after it's been sitting in the queue, queued up, ready to run, by which it's allowed out of that queue onto the call stack. Can anyone take a guess?

[00:10:30]
There's sort of two parts to it. Yeah, go ahead, Matt.
>> off screen male: When the execution context currently running is complete.
>> Will Sentance: Absolutely, so if you've got any on the call stack, gotta be gone. But it's more than that. It's so strict. Yeah, Kayla.
>> off screen female: The global execution context has to be done.

[00:10:48]
>> Will Sentance: It's in fact all synchronous code, all regular execution. Meaning you could have, which is exactly what Kayla's saying, you could literally have a million console.logs in a row. You could have an infinite while loop of console.log, and the queue would never dequeue printHello. It would never even grab it and put it on the call stack.

[00:11:11]
And that, to me, I will admit, when I first realized that, I had to go and check that. I couldn't believe you could literally, literally have a million console.logs. And they would all run before anything was out of the queue. That seems insane, but it actually allows us to be certain of when our code will run out of a queue.

[00:11:32]
It may not be the certain in the sense of I know the moment. But I do know the order. All regular code will run first until I ever touch anything from the queue, until I ever put anything out of the queue. So, how does JavaScript implement that? Well, it has a little tiny feature, very profound feature.

[00:11:54]
But really, it just does this one thing, which says I'm gonna check before every single line of code run. Is the call stack empty? Is the call stack empty? Is there something in the queue? If the call stack is not empty, if there's still further global code to run, if there's still further global code to run, then I will not even go look at the queue.

[00:12:13]
But if the call stack's empty or if I head down to the queue, I grab the function, I put it on the call stack. And what is that known as that little feature? That little feature that does the very, very fast checking every single line before it runs any line of code, it checks.

[00:12:30]
Is there anything on the call stack? If there is, just do it. Is there anything left running global, do it. If it's all finished, head down to the queue. And that feature is known as the Event,
>> Will Sentance: Loop. And it's job is simply to very quickly be checking constantly.

[00:12:48]
Is the call stack empty? Is there anything in the queue? Is the call stack empty? Is there anything in the queue? Is there any global code to run? No, finally I get to go down. So my event loop throughout goes, is the call stack empty at blockFor1Sec, everybody?

[00:13:01]
>> off screen male: No.
>> Will Sentance: No, we stil got to run in blockFor1Sec. At 1,001 milliseconds, is there further global code still to run?
>> off screen male: Yes.
>> Will Sentance: Yeah, so the event loop goes, no, you can't. Finally, when all global code is finished running, what happens? It heads down to the queue, it goes, yes, I'm ready to head down into the queue.

[00:13:23]
It grabs printHello, and it sits on the call stack and executes it. It puts the parenthesis on for us, no problem and runs printHello. And for that until he has six was the entire model of Asynchronous JavaScript. So let's have thumbs on this notion that we have saved our functions for another blockFor1Sec.

[00:13:44]
We use setTimeout to trigger a timer, an associated printHello function was passed to it. Yes, it said 0 milliseconds until that function could be run. But what do we now know that really means? It means that it's 0 milliseconds until that function is put into the, exactly as Peter's hinting, into the callback queue.

[00:14:04]
And then all our global code's gonna continue running, however long it takes. And when it's all done, then the event loop goes, hooray, the Call Stack is done. All global coast finish running, and we grab from the Callback Queue and put printHello in the Call Stack.

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