Lesson Description

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

Will introduces the microtask queue and demonstrates that while synchronous code blocks the call stack, asynchronous callbacks from promises are placed into the microtask queue, which has priority over the callback queue. This causes promise-based functions to run before other callbacks, even if those callbacks were queued earlier.

Preview

Transcript from the "Microtask Queue" Lesson

[00:00:00]
>> Will Sentance: Alright, good stuff people, now we have done all of our background work setup. I think it's fair to say, and so now in our synchronous JavaScript thread, we hit what line after assigning or after attaching our display function using then. Tenzin we hit what line in JavaScript. Um, I believe it's the block for the block for 300 milliseconds, exactly, and this people, is a regular old function, so it's a brand new what Tenzin?

[00:00:31]
Execution context, execution context, it's going to be added to the call stack. There it is, block for 300 milliseconds, and into it we go for 300 milliseconds. Uh, do I want to go, so 300 301, 300, 23334, yeah, I think I'm going to say, so at 2 milliseconds I guess, I'm just. I guess it's the next thing in line, we're going to go inside a block for 300 milliseconds, that is going to run there in JavaScript for 300 milliseconds via a loop or some other thing where we're doing lots of small tasks for a very long time.

[00:01:08]
That's the only way we can block in thread. Uh, while we're in there, ah! Well, actually, sorry, I feel very bad. Print hello. I'm so, feel so bad for Print hello. Was Print hello allowed back on the call stack before we ran Block for 300 milliseconds? Event loop says no. Event loop says no, exactly. Almost a reference to a famous British comedy. Exactly, it was not allowed back on at 2 milliseconds.

[00:01:34]
No, instead we hit our block for 300 milliseconds. I'm so sorry, I assumed that. Like, actually, hello, it's like, excuse me. I wanna come back on, but is it allowed? Event loop says no, because there's still synchronous global code to run. And now there's something on the call stack, so event loop continues to say no. But while this foreground work in JavaScript is happening, you won't believe what's happening back in our web browser.

[00:02:10]
But at about 270 milliseconds. What comes back but our response data from TikTok. Now in practice, this data will come back and we'll need to do some JSON parsing on it to extract the actual thing we want, not the headers, or if you want the headers, the headers. But we're just going to keep it fairly simple. Well, firstly, at 270 milliseconds, therefore, we have. Completed? I should have asked, have you completed?

[00:02:38]
Yes, yes, exactly. And what data do we get back? Well, we actually got a bunch of information about the request, uh, the headers, information about what we've, about TikTok's server, other background info, but in practice, we're just going to make use here for now of the name of our favorite latest video, which is going to be our cute puppies, that we're going to do in purple.

[00:03:06]
Cute. Puppy, there it is, our cute puppy string, that's what we got back, the name of our most recent favorite video. And at that moment. What happens, we're in the middle of block for 300 milliseconds. At that moment. We can update our future data result. I'm going to add a caveat for that in a moment, but for now, at that moment, we now have our data back. What do we do on completion?

[00:03:39]
At 270 milliseconds, we are going to update our future data result value with our cute puppy. There it is, our cute puppy. OK, which means our display function is ready to go. Hooray! Where will it be queued up, people? Of course, well done. You're all going to be completely wrong, but, but, yes, where else would it go? Into the callback queue, let's put it there. Ready, behind, print, hello.

[00:04:13]
It was added there at 270 milliseconds. There it is. And because display is now ready to run, right, because the result value came in and display auto runs, ready to go, but it can't go on the callback queue immediately because we're still stuck here. We're at 270 milliseconds, we're in the middle of the block for 300 milliseconds still. Uh, we've got 2 things in the queue, we are finished with running for blocks for 300 milliseconds, we're outside of it now, we hit 302 milliseconds, we pop.

[00:04:53]
Blocked for 300 milliseconds off the call stack, and. What do we hit as our next task? Well, presumably we go to our callback queue. No, no, no. Well done, everyone. Where do we go first, Chris? Console.log, me first, good old me first, at least it gave us a clue with its name. Uh, and therefore, at 302 milliseconds, we got our me first in our console. OK, but now we hit our 303 milliseconds in JavaScript.

[00:05:36]
And now I assume our poor print hello that was set to run after 0 milliseconds, all the way back at the top here, now it gets to go on the call stack. Right, everybody? Should be right, and yet. In fact, display gets to go on the call stack first. With our input of cute puppy. Cute puppy. Poor old print hello, hm, what is going on here? I'm going to decide what I'm going to say in a second.

[00:06:24]
Display passing. Uh, cute puppy. There it is, and what does display do, a brand new everyone together. That's execution. I see the context, beautiful. Into it we go, where our data parameter on display, Chris, is given what argument automatically. Notice JavaScript added those parentheses. We didn't add those parentheses, when we passed display into future data dot then we just say the definition.

[00:06:51]
But when it's called, it automatically adds parentheses and automatically puts the input of the data in. So what is our argument? Cute puppy going to be assigned to inside of the data core. Oh, to data, perfect. And there it is. Data is cute puppy in our local memory, and we console log data, which is to say, at 303 milliseconds. We console log. Cute. Puppy. But this makes no sense.

[00:07:28]
I know how a queue works. I take the first thing in. Is that right? Yeah, the first thing in is the first thing out. That's right, isn't it? Yeah, the first thing in is the first thing out, not the last thing. Can anyone make an intuitive guess at where or what might have actually happened here? Where do we think display might have actually been added, if not, well, OK. Anyone make a guess, Chris, you wanna give a guess?

[00:07:59]
A different queue. Let's give him a hand. Well done, Chris. An incisive insight from Chris. People, the callback queue, sometimes known as a task queue, is just one, at least within the web browser, of our two important queues, we have a second queue, the microtask queue. And into that. Into that goes all functions that are deferred, by being, to be run later, by being added to promise objects, they never go into the callback queue.

[00:08:40]
It never went, display never went in there. Display went into the microtask queue. There it is, into the microtask queue at its completion of 270 milliseconds, when our data came back and the display function was added to our queue at 270 milliseconds. There it is in the microtask queue. And what might you think the event loop prioritizes as its queue to always check first, Chris?

[00:09:09]
The microtask queue always gets that priority, we always check it first. So when the event loop saw that we had finished running global code with our console log me first, at 303 milliseconds, it did not go to the callback queue where Print hello had been sitting since 0 milliseconds, since the very start, and when, uh uh, checked the microtask queue where display had just rocked up only 32 milliseconds, 33 milliseconds earlier, and it said, don't panic, you're my priority, and it grabbed display, put it on the call stack, passed in our cute puppy data as our argument, and there we had a new execution context and displayed cute puppy, at which point display was now no longer in the microtask queue, was popped off the call stack, popped off the call stack.

[00:10:22]
And finally, at 304. Milliseconds. What do we think the event loop Chris finally said, I'm going to look at you and give you some time. Print hello, Print hello, and print hello was added to our call stack at 304 milliseconds, when it had hoped to be run at after 0 milliseconds. It had to wait all the way through until 304 milliseconds when print hello was finally executed, and what therefore, Chris, at 304 milliseconds was displayed in our console, hello, hello.

[00:11:04]
Oh my goodness. For one thing, by the way, I gotta say, John is going to love our beautiful, colorful whiteboard, uh blackboard here, but wow, it turns out that we don't just have one queue. And our promises, our promise deferred functionality attached to a promise to only be run automatically when some background work completes and the value property is updated, it gets precedence.

[00:11:28]
It gets put into a separate queue known as the microtask queue, and that that queue is checked first. The event loop, as it does it checks every time is global finish, is global finish, is global finish, it is. Don't go first to the callback queue, go first to the microtask queue, which is where display by being promise object deferred was being queued. Once that was done, now finally, JavaScript's engine, the event loop checked, or the event loop, sorry, checked our callback.

Learn Straight from the Experts Who Shape the Modern Web

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