I was reading this blog about event loop and micro/macrotask queues in javascript but I have doubts about the statements from the blog:
In JavaScript, no code is allowed to execute until an event has occurred. It is worth mentioning that the execution of a JavaScript code execution is itself a macro-task.
Macro-tasks include parsing HTML, generating DOM, executing main thread JavaScript code, and other events such as page loading, input, network events, timer events, etc. Examples: setTimeout, setInterval, setImmediate,requestAnimationFrame, I/O, UI Rendering.
What I know is that execution of the javascript code can’t be macro-task unless it is user interaction like a click, setTimeout etc.
I don’t get this beacause all I know is that macrotasks and microtask are generally asynchronous operations and execution of main thread javascript code is synchronous codes like console.log("hello")
. Correct me please if I am mistaken.
By the way, I’m referring to the execution of main thread JavaScript code in the context of script tag in html within a browser environment. Also let’s assume that script is linked as a external file(not directly embedded within HTML)
2
Answers
This is inaccurate. The macrotask queue only contains scripts and javascript callbacks.
For example, if you call
setTimeout
, the callback is only added to the macrotask queue when thesetTimeout
completes. It is not the case that thesetTimeout
itself is a macrotask. It is the javascript callback, and not the call itself, which is the macrotask.Similarly, when network I/O completes, the javascript callback function will be placed on the macrotask queue. But the network I/O itself is not a macrotask.
DOM element event listener callbacks are placed on the macrotask queue when the event occurs. The same applies to callbacks from
setTimeout
,fetch
, etc.All javascript execution is single-threaded (unless you have multiple web workers).
Javascript single-threadedly executes anything in the microtask and macrotask queues until those queues are empty, and then waits until new tasks are added.
It therefore makes sense that the initial Javascript code that is run when a web page loads is itself a macrotask.
It depends on what kind of script you’re talking about, and which environment.
For HTML, most of the time you’ll be in a task (there is no such thing as a macrotask, only tasks and microtasks).
For instance inline scripts met by the parser when the browser navigates will be executed from the global task the navigate algorithm queued. External scripts will be executed from the fetch task that got queued when fetching the script’s content.
defer
scripts will be executed after the browser spinned the event loop, which will itself queue a task to then run the script.But, you could force being in a microtask too. For instance doing
Here when the parser meets the inline script, it’s still in the microtask that launched it, so the script is executed from that microtask.
In node, CommonJS scripts are executed from … a magic point which is called the main module. It’s not really a task, but it’s not a microtask. ESM scripts on the other hand are executed from a microtask(, itself queued from an IO task).