 OK, so this is a mess. Even for this one, I have once again. Oh, more dead trees. Excellent. More nose, yeah. Great. Well, I did two pages on one to minimize the dead tree-ishness. Let's get into it. Yeah, this is going to be an interesting one, because. I'll tell you what. I'll call it. Like, don't tell me it's interesting, so I'll be the judge. Everyone on YouTube will be the judge. Like, don't come at me with your, this is an interesting episode, unlike the ones you did. Thanks, mate. I thought this is an interesting one, as in I'm not sure I got it right. I'm pretty confident. But I thought, oh, this is going to be a nice snappy shot, three minutes. You know, in the spirit of micro trips, almost. And now I'm at the point where it's messy, and I hope I got it all right. And I'm pretty sure some Node implementers core team member will go, well, actually, there is more detail to this. And we welcome that, like, good old bit of fact-checking. Don't just leave us to our ignorance. All right, so obviously, we're talking about tasks. Wait, you're just ripping off my content. This isn't your content. If you just printed off my talk, what's going on? Well, in my defense, I created a Google link for you that went, go straight to your talk. Because actually, your talk is kind of the basis for this, because I'm not going to explain the event loop, because you did much better than I care to do. But it turns out there is more things that I found out that you didn't either intentionally didn't include, or maybe just didn't even know about yourself. Who knows? Let's say intentional. Let's just go for intentional. Yes, you all know this already. I'm just filling in the gaps. No, probably not. But the talk is, I mean, it's pretty popular, I think. But in case any one of our viewers hasn't seen it, here's a link very much worth watching. And you can enjoy how all of my jokes just fall absolutely flat with the audience. That's my favorite bit about that talk, even on stage, as I was like, da-da-da-da-da-da. All right, let's get into this. I am making up some functions. These functions don't exist, but we will implement them in the course of this video. I'm actually kind of sad they don't exist, some of them, because it turns out the different ways to schedule tasks in JavaScript are called anything but something sensible. So I want to start with three different ways of scheduling a callback function. There's a way to synchronously call a callback. There's a way to call a callback as a task, and there is a way to call a callback as a microtask. Now, what I found weird when I went through this is the realization that actually we have tasks and we have microtasks, which kind of conveys a sense of size, a microtask sounding smaller than a task, but really what it just means, the microtask has a higher priority than a task. It doesn't really say anything about the amount of work that you can do it. Maybe a bit about what you should do, but in the end, the event loop is just something that spins around and takes tasks out of different queues, and these different queues have different priorities. So let's start at what that means. So if we were to run this, the synchronous stuff would run immediately because synchronous stuff doesn't give the event loop a chance to spin at all, then it would go on to the microtasks because microtasks have a higher priority, and then we'll go on to the tasks, which are the only queue that is left at this point. Anything you want to complain about at this point, Jake? I did try and think of a situation where there is very particular situations where microtasks can come before tasks, but only when they're queued by the browser, not by JavaScript. So do you know what, other than that, I'm very happy so far. In terms of having these as actual functions, there is a proposal for a microtask, a queue microtask. Hold that top, we're gonna get to that. Oh, okay. Looking forward to it. So what does it mean to schedule a callback synchronously? Well, you call it, and that's because that way you don't yield to the event loop to let it spin around and look at which queue to run next. You say, no, no, call this function, and it will go ahead to the engine and call the function. So that one, I hope, is pretty straightforward. But microtasks are interesting because I actually Googled a bit to see what people recommend and I saw some very interesting and wrong recommendations. One of my favorites was this one, which is not correct because the constructor of the promise, the function inside the promise constructor, this is called the revealing constructor pattern, I think, I'm pretty sure. That one is invoked synchronously. So this, the function that you pass to the constructor is called immediately, the event loop doesn't get to spin at all. So this is not. But what people were thinking about, I think, when they were saying this, is that it has to do with promises because the dot then of a promise is scheduled in a new microtask. So this would be the classic way to schedule a callback in the next or in a microtask. But as you already said, there is queue microtask and queue microtask actually has landed pretty much everywhere. So the nodes, we have it in Safari and Chrome and Edge and Firefox. That happened without me noticing. I didn't know it either. And I'm so happy because this is a really nicely named function and it turns out for all of the other task types that we're gonna discover, these kind of don't exist. So this is how you would schedule a microtask. Let's talk about tasks. Now, tasks are probably the oldest and most fundamental task type because that's what the event loop and JavaScript was built around. And yet it is surprisingly hard to just schedule a task. What most people recommend or give you when you go for it is set timeout with a timeout of zero. And that is both correct and incorrect. Most of the time that will be okay. However, set timeout has some very specific rules that when you start scheduling tasks from within tasks using this, once you reach a certain depth, timeout clamping will occur. So it won't schedule a task immediately but it will start scaling it after four milliseconds. And both in browsers and in node, interestingly enough. So that's something to be mindful of. Yes. The spec for this says like is, you know, wait whatever time you put in there is a zero in this case but then the browser is free to add any kind of padding that it wants. Yes. And as you say, as the chain cap gets to a certain amount, the spec says four milliseconds, I think, but the browser can do whatever it wants beyond that. So yeah, it's... I think we have a previous two or three episode on this. Do we, Jake? Yes, we do. Well, we should link to it. Oh, depending on the broadcast order of the episodes we're filming. So yeah, this will work at a service level but if you get into it, it can start behaving weirdly. So a more reliable but surprisingly complicated way that I often use relies on message channel. Because what we can do is we create a message channel which is basically just a pipe with post message, send an empty message in on the one side and wait for it to come out the other side because these kinds of events are scheduled as a task. So event dispatch to call all the event is a task that gets scheduled by the engine. And so we can basically just call the call back in the message handler. Don't forget to call start because the message channel will just buffer messages until you tell it, okay, I'm ready to receive the messages now. So this would be a more reliable way with no timeout clamping or anything to interfere to schedule a task. I have used this in production. At that point I would recommend moving the message channel to a global and sending IDs so you don't have to create message channels over and over, but I thought for the sake of this slide I'm gonna keep it a bit simpler so it's easier to read. Yeah, so the reason we don't have like a simple function for queuing tasks is because there are many task queues and whenever someone suggests, let's have a simple function for queuing a task, the next question is which queue and everyone goes, oh yeah, it's a problem. And then... Yeah, and we're gonna discover that in a bit as well. One thing I think that I wanna point out is the API that a certain function, like the way a function is exposed to you, like here the do work function clearly returns a promise. That doesn't mean that it will call that function in the next microtask because under the hood it could do anything. It could use the task function to actually only resolve the promise in the next task. So the API that is exposed to you only tells you the minimum priority or the minimum delay that can occur, not nothing about the maximum because I've seen some people say, I see that talk about like web Bluetooth API which uses promises and they were kind of assuming that it will be resolved within a task. That's not the case. So this is a lower bound, not an upper bound. Yes, a promise which has already resolved will schedule a microtask straight away for a reaction. But yes, other than that, I mean, Fetch for instance, is going to go away and do a network call. So that's gonna take a while. And yeah, that's the same with Bluetooth, right? It's gonna go away and do something with something outside of the immediate machine. So yes, that takes time. Exactly. So now we're getting into the more arcane territory because have you heard of nanotasks? In passing, but not really. So I only heard them. I didn't know what they were. Also it's like, if we have now micro nanotasks, where are the millitasks? I think there is a gap that we need to fill. Nanotasks, so the thing is, for example, I don't know if they're actually called nanotasks, but what I'm saying is there is a task type that has a higher priority than microtasks, which I thought was quite interesting. It only exists in Node. It does not exist on the web, although they were talked about maybe adding it to the web. I'm still not quite sure what the benefit would be, but let's look at it. So let's play this game again, where we schedule a couple of console logs in a task, a microtask, a nanotask, and synchronous. And if everything goes right, what we should see is the task with the highest priority prints first, which is synchronous, then nanotask, then microtask, and task. So the question is, how do you schedule a nanotask? Any takers, Jake? Oh, okay then. What do we have in Node? Okay, so there is a task API in Node, but I assumed that was microtasks. Or did they call it like schedule job or something? I haven't even encountered that one. Maybe there's more that I could have covered. Oh, I'm maybe making it up just to... And what I'm trying to do right now is avoid just saying, I don't know, because really that is the trick. I didn't know before I did the research, so don't be ashamed. It is next tick. Next tick, that is the one I was thinking of. But I thought that was microtasks. See, I would have thought it is a task, because I feel like a tick is kind of what people say for one spin of the event loop kind of thing. And to me, okay, it's gonna look at the next task. But actually something you schedule with next tick has a higher priority than a microtask. And as such has been, I guess, colloquially dubbed as a nanotask, which, you know, that's in it. And next tick, process of next tick, obviously doesn't exist in the browser. They were talking about it for custom element callbacks and maybe even mutation observer, but none of that has happened. Those all just are either synchronous or microtasks at the time of recording. So what's the point in set? I don't know. I literally don't know. But things are gonna get even weirder, Jake. So set immediate is an API that used to exist in the browser, specifically IE. I don't think any other browser ever shipped it. And it's been, since been retired, it does still exist in node. So let's play this game again. Let's schedule a bunch of console logs. What do you think? From what you said before, nanotask, microtask. And my understanding, in the web spec, set immediate was a task. And part of the problem with the APIs, again, the question came up, which task queue? So I'm going to guess that set immediate comes before task, but I imagine that it would all depend on which task queue in the web, but I actually don't know how many task queues there are in node. That is pretty close to the truth. That being said, pretty close to my truth, which might be wrong because I'm still, this is the one I'm least sure about that I got it right. So if you run it this way, if we use my task function using message channel and all the other ones as we talked about, this is the output. It has a lower priority than a normal task, reliably. Now, looking at the documentation, set immediate says it runs a callback. It doesn't even mention the word task, but it says it runs the callback when all IO has finished. And that made me think because technically- It's more like idle callback than request idle. That's pretty close, actually, because I was thinking, well, message channel, a post message, is that considered IO? Maybe it could be. And so I tried the same experiments, but with set timeout. And what happened? They switched. So what I have deduced from this is that set immediate schedules a normal task, but similar to request idle callback, it only gets processed when there is no IO queued up to happen. So it has- There's something about the word immediate that doesn't instantly scream out to me after loads of other stuff is done. So that's what I think. I think set immediate is the least immediate way you could schedule a callback in Node. Great, excellent. Brilliant. So yeah, in a way, it's the closest thing that Node has to request idle callback, but yet at the same time, it is miles away from being the same thing. So I'm gonna, let's ignore set immediate. I don't think it has a lot of use cases. And if you do, please write a wrapper function with a better name so people know why you're using it. But all in all, maybe this might be useful for the one or other person. Quick, nice shortcuts, how to implement scheduling functions. I commented out Nanotask because that one doesn't exist on the web, but it's there for our friends who use Node. So maybe this slide is helpful to someone and maybe some people working on Node can tell me if I got set immediate right. Drop that in a gist and pop it in the description. I shall do that. Well, see you next time. Uh, b-roll. Let's see if I can get them back in. What's going on? Sorry, talk to me. It's connected. Now I'm gonna sound like because it's doing the wrong microphone. I don't think you can hear us.