Eventloop learning notes

Introduction to the

The Event Loop is an execution model

Macro queues (MacroTask or Task) and microqueues (MicroTask or Jobs)

Macro queue

The macro task Queue calls the callbacks of asynchronous tasks in turn.

  • setTimeout
  • setInterval
  • SetImmediate (Exclusive to Node)
  • RequestAnimationFrame (browser only)
  • I/O
  • UI Rendering (browser only)

The queue

Other callbacks for asynchronous tasks are placed in the Micro Task Queue and wait for the order to be invoked

  • Process. nextTick (Node only)
  • Promise
  • Object.observe
  • MutationObserver

The complete flow of the browser Event loop (important)

  1. Execute global Script synchronization code, some of which are synchronous statements, some of which are asynchronous statements (setTimeout, etc.);
  2. After executing the global Script code, the call Stack is emptied;
  3. Remove the callback task at the beginning of the microtask queue from the microtask queue and put it into the call Stack for execution. After execution, the length of the MicroTask queue decreases by 1.
  4. Continue fetching the task at the top of the queue, place it on the call Stack, and so on until all the tasks in the MicroTask Queue have been executed. Note that if a microtask is created in the process of executing it, it is added to the end of the queue and executed during this cycle.
  5. When all tasks in the MicroTask Queue are completed, the MicroTask Queue is empty and the call Stack is empty.
  6. Remove the task at the head of the macroTask queue and add it to the Stack for execution.
  7. After the execution, the call Stack is empty.
  8. Repeat steps 3-7;
  9. .

Note: macro queues only perform one task at a time, and microqueues are completed only when all tasks in the microqueue are completed

console.log(1);

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

setTimeout((a)= > {
  console.log(9);
})

console.log(10);

/* 1, 2, 3, 4, 5, 6, 7, 8, 9 */
Copy the code

When a new microtask is created during the execution of the microqueue, the microtask is added to the end of the microqueue and is executed in this cycle until the microqueue is empty (in the case of process.nexttick () in NodeJS, this is capped at 1000 microtasks).

NodeJS the Event loop

Process (Critical)

  • Timers stage: This stage performs callback scheduled by setTimeout and setInterval
  • I/O Callback phase: Execute callbacks except for close events, callbacks set by Timers, and callbacks set by setImmediate()
  • Idle, prepare: Used only internally
  • Poll phase: Fetch new I/O events, where node will block under appropriate conditions
  • Check phase: Perform the Callbacks set by setImmediate()
  • Close Callbacks: execute socket.on(‘close’,….) These callbacks

NodeJS has four MacroTask queues.

  1. Timers Queue
  2. IO Callbacks Queue
  3. Check Queue
  4. Close Callbacks Queue

In browsers you can think of a single macro queue, where all macro tasks are in the same macro queue, whereas in NodeJS, different macro tasks are placed in different macro queues.

Microqueues in NodeJS

Mainly include:

  1. Next Tick Queue: To place the process.nexttick (callback) callback task

  2. Other Micro Queue: Places Other microtasks, such as promises

In a browser you can think of only one microqueue to which all microtasks are added. In NodeJS, different microtasks are placed in different microqueues.

Execute the process

  1. Synchronous code that executes the global Script
  2. To execute microtask tasks, execute all tasks in the Next Tick Queue and then all tasks in the Other MicroTask Queue
  3. Macrotask is executed in 6 phases (the 6 processes above). All tasks in each phase of macrotask (all tasks in the macrotask queue of each phase) are executed from the first phase. When the macrotask of each phase is completed, the micro task is executed, that is, step 2
  4. Timers Queue-> Step 2->I/O Queue-> Step 2->Check Queue-> Step 2->Close Callback Queue-> Step 2->Timers Queue

Note: when a new macro task is generated in the macro queue, it will not be executed until the next queue starts. If setTimeout has a limited time, then if the Timer Queue does not have a callback, it has to wait until the next one is executed, or its callback is registered with the Timer Queue.

console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')})})new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})
process.nextTick(function() {
  console.log('6');
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')})})/* the correct answer is 1
Copy the code

In the Microtask phase, all tasks in the Next Tick Queue and Other Microtask Queue are executed before entering the macro task in the Next phase

SetTimeout versus setImmediate

  • SetTimeout (fn, 0) is executed in the Timers phase and is executed only in the poll phase (to obtain new I/O events) to determine whether the specified timer time has been reached
  • SetImmediate (FN) performs in the Check phase
Execution order
  • If both are called from the main Module, the execution order is random, depending on process performance
  • If neither is called in the main module, that is, in an I/O Circle, then the setImmediate callback is always executed first because the Check phase is reached first
SetImmediate vs. Process.nexttick
  • The setImmediate(FN) callback task is inserted into the macro Check Queue

  • The process.Nexttick (FN) callback task is inserted into the microqueue Next Tick Queue

  • The process.nexttick (fn) call is limited in depth to 1000, while setImmedaite is not

    Browser:

NodeJS:

Resources: segmentfault.com/a/119000001…