1. What is an Event Loop? What problem does it solve?

  • Event Loop is a kind of operation mechanism of computer system.
  • Browsers and NodeJS implement their own Event loops based on different technologies.
  • EventLoop solves the limitations of the single-threaded model on JavaScript because all tasks are done on one thread. When faced with a large number of tasks or a time-consuming task, the page will appear “suspended” because the JavaScript will not stop and will not respond to the user’s actions.

2. What is the execution mechanism of Event Loop in browser? What are macro tasks and micro tasks?

The simple understanding is:

  • In the renderer process, there is a message queue, which is used to hold tasks.
  • There is an IO thread that receives incoming messages from other processes (such as the resource load of the network process or the mouse click of the browser process), assembles these messages into new tasks, and adds new tasks to the end of the message queue.
  • There is also a main thread that reads tasks from the message queue header in a loop and executes them.

The task types of message queues are: input events (mouse scroll, click, move), microtasks, file reads and writes, Websockets, JavaScript timers, and so on. In addition, the message queue contains many page-related events, such as JavaScript execution, DOM parsing, style calculation, layout calculation, CSS animation, and so on.

To name a few 🌰 :

  • When the HTML document data is received, the rendering engine adds a “parse DOM” event to the message queue
  • When the user changes the window size of the Web page, the rendering engine adds the “relayout” event to the message queue
  • When the JavaScript engine garbage collection mechanism is triggered, the rendering engine adds the “garbage collection” task to the message queue
  • To execute a piece of asynchronous JavaScript code, you also need to add the execution task to the message queue

We call the tasks in the message queue macro tasks. Micro tasks and macro tasks are bound, and each macro task creates its own micro task queue when it executes. If you create a macro task and a microtask for callbacks in a macro task, the microtask precedes the macro task in any case. When executing a JavaScript script, the general classification is as follows: macro task: whole code script,setTimeout, setInterval microtask: promise. then(non-new Promise) code after await

Summary: Execute the macro task, and then execute the microtask generated by the macro task. If a new microtask is generated during the execution of the microtask, continue to execute the microtask. After the execution of the microtask, return to the macro task for the next cycle.

3. Having said so much, I can understand and digest it by myself through the following 小题

    async function async1() {
      console.log('A')
      await async2()
      console.log('B')}async function async2() {
      console.log('C')}console.log('D')

    setTimeout(function () {
      console.log('E')
    })

    async1()

    new Promise(function (resolve,reject) {
      console.log('F')
      setTimeout(function(){
      console.log(999)
      })
    }).then(function () {
      console.log('G')})console.log('H')
Copy the code
  1. The entire code is parsed as a macro task, and then executed, console.log(‘D’), printing D.
  2. When setTimeout is encountered, its callback function is a macro task, and it is placed in the macro task queue.
  3. When async1() is encountered, console.log(‘A’) is executed and output A, await async2() is executed and output C. The code after the next line of await is placed on the microtask queue as a microtask.
  4. If you see a new Promise, print F. The setTimeout callback is placed in the macro task queue as a macro task. Then to the microtask queue.
  5. Output H.
  6. After the first round of macro tasks is completed, the microtask object is checked to see if it is empty.
  7. At this point, two microtasks are taken out and executed one by one.
  8. The output B.
  9. Resolve () will not print G, undefine will not print.
  10. The microtask is complete. The next macro task starts. There are two setTimeout callbacks in the macro task queue. O E. Then check the microtask queue, none. Then start the macro task and print 999.
  11. So the output is D, A, C, F, H, B, undefinded, E, 999.
console.log(1);

setTimeout(() = > {
  console.log(2);
  Promise.resolve().then(() = > {
    console.log(3)}); });new Promise((resolve, reject) = > {
  console.log(4)
  resolve(5)
}).then((data) = > {
  console.log(data);
})

setTimeout(() = > {
  console.log(6);
})

console.log(7);

Copy the code
  1. Output 1.
  2. The setTimeout callback is placed in the macro task queue as a macro task.
  3. New Promise, output 4, then put the callback into the microtask queue.
  4. SetTimeout is encountered again, and the callback function is put into the macro task queue as a macro task.
  5. Output is 7.
  6. Then check the microtask queue and print 5.
  7. After the microtask queue is complete, the next macro task starts.
  8. The first setTimeout callback, which prints 2. When you encounter promise.then, put it into the microtask queue. When the second macro task is completed, check its corresponding microtask and output 3.
  9. The microtask queue finishes, the next macro task starts, and 6 is output
  10. So the output is: 1, 4, 7, 5, 2, 3, 6