preface

Knowledge of the browser’s EventLoop will help us understand how the browser’s rendering process works and how it works when we write code later.

How does a browser work

We know that the work of the page depends on the event loop mechanism, so how does the event loop mechanism work? Next, we will analyze step by step!

We know that browsers execute task by task, i.e., single thread. This is easy to understand, but we know that when we operate the page, such as mouse click events, keyboard operation events, these events are not fixed and irregular, so how can the browser ensure that these times are real-time and orderly.

The way the browser works in this case is that it first stores tasks in the data structure of the queue. The queue structure is first in, first out, and works well with browser events. We push new events to the end of the queue. Let’s say we first click on an input box with the mouse, and then we enter information in the input box. At this time, there are two events in total, as shown below:

After using the data structure of queue, the order of events can be guaranteed

The real time

Does the browser know when I’m going to trigger something? How did he execute the event I triggered?

The way the browser implements this is that it constantly polls for tasks in the queue to execute, essentially a for loop that takes tasks from the queue and executes them, and then repeats the process again until there are no more tasks in the queue. As shown below:

Macro and micro tasks

Browsers divide tasks into macro tasks and micro tasks. Let’s look at these two types of tasks, starting with macro tasks.

Macro task

Macro tasks are common: ① HTML parsing events, ② user interaction events, such as the above click events and keyboard input events, ③ JS code execution, ④ Some Web Api events, such as setTimeout, setInterval, etc.. Normal macro tasks are pushed to the end of the queue and executed in sequence, as described above, but delayed execution apis such as setTimeout are not handled differently.

Timer flow in eventloop

If we push the timer callback function into the task queue like a normal macro task, then if there are too many tasks in front of the timer, the execution time is longer than the timer set, then the timing will not be able to achieve this feature. So the browser created another queue specifically for the timer macro task – delay queue.

The main thread of the browser will push the TIMER ID, callback function, launch time and delay time into the delay queue. When the event loop system executes a macro task, it will go back to check whether any task in the delay queue has expired, and if so, it will execute the task. Why it is often said that setTimeout should not be used to execute some events with high precision requirements, such as using setTimeout to achieve animation, this is because if the execution time of the current task is too long, the expiration time set by the timer will not match the expected time, resulting in some delays.

Micro tasks

Microtasks mainly include MutationObserver, promise.then () and other events. Microtask is used to solve the problem of asynchronous callback. Each macro task carries a microtask queue, which will check whether there is a task in the microtask queue when the current macro task is about to finish executing and exit the macro task. If there is a task, the microtask will be executed.

Code to rehearse

    console.log(1);
    Promise.resolve().then((res) => {
      console.log(2);
    });
    setTimeout(() => {
      Promise.resolve().then((res) => {
        console.log(3);
      });
      console.log(4);
    }, 0);
    console.log(5);
Copy the code

The js code belongs to the macro task, and under the current macro task, we see promise.then () so we put it in the microtask queue of that macro task, and then we encounter the setTimeout timer, and we put it in the delay queue, because setTimeout is also a macro task, So it will also have its own microtask queue, and we put promise.then () from the setTimeout callback into its microtask queue. Then let’s start the analysis:

(1) the task of the current macro js code execution, print 1 first, and then will print 5 (2) after the macro code execution of task will be to find it if there is a task in the task queue, check here to a task, it will output 2 (3) the current macro tasks have been performed, went back to see if there are any more tasks due time delay in the queue, 4. Check if there are any tasks in the microtask queue after executing the code. Here is a promise.then () task, execute output 3

The final output is: 1 5 2 4 3

conclusion

I hope my carding can bring you a little effect, if not good, please include, thank you ^.^