Check out a free preview of the full The Hard Parts of Asynchronous JavaScript course
The "Microtask Queue Q&A" Lesson is part of the full, The Hard Parts of Asynchronous JavaScript course featured in this preview video. Here's what you'd learn in this lesson:
Will answers questions from students about browser methods and queues, the priority of code being processed through event loop, and more.
Transcript from the "Microtask Queue Q&A" Lesson
[00:00:00]
>> Speaker 1: Let's have thumbs on it. You lost me long ago.
>> Speaker 2: [LAUGH]
>> Speaker 1: It was a mistake coming here today. I'm clear.
>> Speaker 2: [LAUGH]
>> Speaker 1: I have clarifications. Everybody, it's okay to have clarifications. Michelle has one. Alec has one. Paul has one. And Paul, you kick us off.
[00:00:16]
>> Speaker 3: I'm just curious if there are any common browser methods or others that drop to the microtask queues instead of the call back queue?
>> Speaker 1: So there are, so you can go and look up. The way you find out, you have the jobs at spec cuz actually MDM doesn't say, I don't think.
[00:00:35]
You got the jobs at spec and you see where does it go? Which queue does it go to? Or say it'll say certain task like I believe event dorm changes. Dorm manipulation changes I believe, you have to check this yourself, go to the job queues. I will say in the spec.
[00:00:56]
The task triggered by the dominant page is in the job queue. Whenever you see job queue it means micro task queue, versus task queue which is typically the term they use for the call back queue. So you can see on a feature by feature basis in the spec which one it get's sent to.
[00:01:10]
And by the way it's a spec. Specs are, we may or may not implement this way. So for a long time, browsers other than Chrome through promise deferred functionality not on the micro task queue. They put it on the back of the call back queue. This is a spec.
[00:01:29]
A spec is like this is how it should be implemented. It's up to you. Now, I'm pretty sure they all implement it the same way with the micro task queue. But it's not by default. I mean it's not like that is how the world must, now it's just guidance by the designs of your JavaScript.
[00:01:43]
Kind of crazy, but now you know why behind the scenes is these two things that might be in conflict. One comes first, or the other, in different browsers. All right, great question, Paul. Very nice. Was it, who else had a clarification? Michelle?
>> Speaker 4: So when future data.value gets set, it kind of seems like that escaped all of the handling in the stack and everything, and it's just kind of magically done almost instantaneously, on complete.
[00:02:12]
Are we missing a step there or is it magic?
>> Speaker 1: Everything that you do is being handled in an event loop. But we can assume in that case that it's giving absolute priority, because it is done before any of this function execution work. So the thing that would block our functionality being updated.
[00:02:33]
So this value here has no interest except in the functionality, it's kicking off. So for our purposes, all that matters is the functionality that's been kicked off. So this always takes precedence, as far as I can tell, over anything that would lead us to be surprised the display is being delayed running.
[00:02:56]
>> Speaker 4: So just to-
>> Speaker 1: It'll just be one final thing, Michelle. The only bottleneck on display running is our event loop prioritizing synchronous code, not something else. So that the value being the block on running, I can't see any evidence that would have been blocked. So we don't need to worry about when it gets updated.
[00:03:14]
It's always gonna take precedence. Okay, as far as I can tell.
>> Speaker 4: So it's not so much that if you were able to somehow magically preempt in your global contacts, and call value that you would have it, but that value is made available to on fulfill at that point.
[00:03:32]
>> Speaker 1: Correct, and actually just this morning I was testing whether you can view value earlier. And so I think value's assignment still happens after all of the call stack work is done. So it's at the end of the event loop cycle. In other words, the event loop is gonna always grab all of the call stack, always gonna do all the synchronous code first before add this value.
[00:03:53]
But that has no implications because it's never gonna trigger a function anyway until all that work is done. So if that happens at the very end, and then it triggers the function, we know that functions are not going to be triggered until that point anyway, so who cares when that gets updated.
[00:04:08]
Okay, there was one other one. Rick, or it was Alex, sorry, Alec.
>> Speaker 5: Yeah, I think it's kind of similar to that last question. I was wondering if the onFulfilled functions get added to the microtask queue and then value is updated in the meantime. Like I'm not sure if that would ever happen.
[00:04:32]
>> Speaker 1: What a good question. The microtask queue, that's such an interesting question. The microtask queue is designed that the event group doesn't leave it until it's finished all tasks in it. Meaning, by the way, if you had inside display and auto resolve promise, it would instantly trigger a function to be passed to the microtask queue to be clear on that.
[00:04:52]
The promise object auto complete, auto had it's value and therefore triggered the unfulfillment function or the functions in unfulfillment. They would be added straight to the microtask queue. The event would never leave the microtask queue. It would never actually reach the callback queue again. You can starve the callback queue, that means prevent the callback queues functions from running by the microtask queue by it's design.
[00:05:17]
The micro microtask is designed that when the event loop is grabbing things from it, as long as there's something in there, it ain't leaving even if you're adding more as you go. So you can always sort of think of it as an infinite while loop on picking out tasks from the microtask queue.
[00:05:31]
It's very, very interesting. I wanna add a few extra conditions to this. Everybody who knows promises knows there's another property on here called status. It has 3 values. It can be pending, resolved, projected, okay? It defaults to pending when we first return out the object. That just means I don't yet have a value in value.
[00:05:56]
I don't yet have a thing for the value. My background work is no where near done yet. When this background work successfully responds, that status, property, we can even write it in, that status, property.
>> Speaker 1: And this is a visible property. That status, property, becomes resolved. And actually it's that that triggers theonFulfillment array of functions to run with this value.
[00:06:22]
But [SOUND], whatever. There's another output the status can get which is rejected. Rejected is when there's some error in the background work. Something errored, maybe the server status came back with an error. You didn't get a successful response. And that's not gonna trigger a OnFulfillment array of functions.
[00:06:44]
It's gonna trigger a different array of functions on rejection. And those functions, how do we get functions in there? And that array, how do we get functions in there?
>> Speaker 6: [INAUDIBLE]
>> Speaker 1: Correct, we parse them to future data, not .then but .catch. And the function we pass the .catch will be stored in the rejection array of functions and be triggered there.
[00:07:08]
We can also parse it as the second function to then, parsing here, like I don't know, error function. And that will be parsed, not to OnFulfillment, but to a different array of functions in here called, onRejection. So if we get an error in any of this process, it will not trigger display.
[00:07:29]
Instead, it will trigger the array of functions known as the onRejection array.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops