This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021

What is a macro task

  • We can treat the code executed on each execution stack as a macro task (including fetching event callbacks from the event queue and placing them on the execution stack each time)
  • Each macro task is executed from start to finish and nothing else is performed.
// Macro tasks --> Render --> Render...Copy the code

The main code block, setTimeout, setInterval, etc., are all macro tasks

First example:

We can put this code in the browser console and do the following to see what happens:

document.body.style = 'background:black'
document.body.style = 'background:red'
document.body.style = 'background:blue'
document.body.style = 'background:grey'
Copy the code

The result is that the background of the page suddenly turns white. The code above is the same macro task, so the page rendering is triggered when all the UI changes are executed. The GUI thread optimizes and merges all the UI changes while rendering, so visually the page only turns gray

Second example:

document.body.style = 'background:blue';
setTimeout(function() {
    document.body.style = 'background:black';
}, 0)
Copy the code

I’ll see that the page appears as a blue background, and then suddenly as a black background. This is because the code above belongs to two macro tasks. The first macro task executes the code to turn the background blue, then triggers the render to turn the page blue, and then triggers the second macro task to turn the background black

What are microtasks

  • We already know that when the macro task is done, we do render, and then we do the next macro task,
  • A microtask can be understood as a task that executes immediately after the current macro task executes.
  • That is, when a macro task completes, all microtasks generated during execution will be completed before rendering.

Promise, process. NextTick, etc., are microtasks.

First example:

document.body.style = 'background:blue'
console.log(1)
Promise.resolve().then(() = > {
    console.log(2);
    document.body.style = 'background:black'
})
console.log(3)
Copy the code

Let’s do it and see what happens

  • The console prints 1, 3, and 2 because the callback for the Promise object’s then method executes asynchronously, so 2 prints last
  • The background color of the page went straight to black without going through the blue phase, because we set the background to blue in the macro task, but performed the microtask before rendering, which turned the background to black before rendering

Second example:

setTimeout(() = > {
    console.log(1)
    Promise.resolve(3).then(data= > console.log(data))
}, 0)

setTimeout(() = > {
    console.log(2)},0)

// print : 1 3 2
Copy the code

The above code contains two setTimeout, that is to say, except for the main code block, there are two macro tasks. In the execution of the first macro task, output 1, and create a microtask queue, so the microtask is executed before the execution of the next macro task queue. In the execution of the microtask, output 3, after the execution of the microtask, Execute the next macro task, and output 2

conclusion

  • Perform a macro task (fetch from event queue if not in stack)
  • If a microtask is encountered during execution, it is added to the task queue of the microtask
  • Execute all microtasks in the current microtask queue immediately after the macro task is executed (in sequence)
  • When the macro task completes, the render is checked, and the GUI thread takes over
  • After rendering, the JS thread takes over and starts the next macro task (fetched from the event queue)