First, why is there Event Loop

JavaScript tasks can be divided into synchronous and asynchronous two kinds, their approach is also different, synchronization task is directly on the main thread queue an execution, asynchronous tasks are placed in task queue, if there are multiple asynchronous task requires in the task queue waiting in line, task queue is similar to the buffer, task the next step will be moved to the call stack, The main thread then performs the task of calling the stack.

Call stack: The call stack is a stack structure. A function call will form a stack frame, which contains the context information such as the parameters and local variables of the currently executing function. After the function is executed, its execution context will pop out from the stack.

JavaScript is single-threaded. Single-threaded means that there is only one thread in the JS engine that parses and executes JS code, and it can only do one thing at a time. However, in ajax requests, the main thread will do other things while waiting for a response. When the response comes back, the callback function is added to the task queue to wait for execution without blocking the thread, so js handles ajax requests asynchronously.

In summary, the process of checking if the call stack is empty and adding a task to it is called the Event loop, which is at the heart of JavaScript’s asynchronous implementation.

2. Event Loop in browser

Micro – Task and Macro – a Task

There are two types of asynchronous queues in browser-side event loops: Macro (macro task) and Micro (micro task) queues.

Common macro-tasks: setTimeout, setInterval, script, I/O, UI rendering, etc.

Common micro-task: new Promise(). Then (callback), MutationObserve, etc.

requestAnimationFrame

RequestAnimationFrame is also a method that executes asynchronously, but it is neither a macro task nor a microtask. As defined in MDN: Windod. hot questAnimationFrame() tells the browser that you want to execute an animation and asks the browser to call the specified callback to update the animation before the next redraw. This method takes as an argument a callback function that is executed before the browser’s next redraw.

RequestAnimationFrame is executed before GUI rendering, but after Micro-Task, but requestAnimationFrame is not necessarily executed in the current frame. It is up to the browser to decide which frame to execute according to the current policy.

The event loop process

  1. Check whether the Macro-Task queue is empty, to 2 if not, or to 3 if not
  2. Execute one of the tasks in macro-Task.
  3. Continue to check whether the Micro-Task queue is empty, to 4 if so, or to 5 otherwise.
  4. Take out the task in micro-Task and return to Step 3.
  5. Perform view updates.

When a macro task is executed, it checks to see if there is a microtask queue. If yes, all tasks in the microtask queue are executed first. If no, the first task in the macro queue is read. During the execution of the macro task, microtasks are added to the microtask queue one by one. When the stack is empty, the tasks in the microtask queue are read again, and so on.

Node Event Loop

The Event Loop in Node is a completely different thing from the Event Loop in the browser. Node.js uses V8 as the PARSING engine of JS, and libuv designed by myself is used for I/O processing. Libuv is a cross-platform abstraction layer based on event-driven, which encapsulates some underlying features of different operating systems and provides a unified API externally. The event loop mechanism is also implemented inside it.

The operating mechanism of node is as follows:

  1. The V8 engine parses JavaScript scripts.
  2. The parsed code calls the Node API.
  3. The Libuv library is responsible for the execution of the Node API, and it assigns different tasks to different threads, forming an Event Loop that asynchronously returns the execution results of the tasks to the V8 engine.
  4. The V8 engine returns the results to the user.

The six stages

The event loop in the Libuv engine is divided into six phases, which are repeated sequentially. Each time a phase is entered, the function is fetched from the corresponding callback queue and executed. When the queue is empty or the number of callback functions executed reaches a threshold set by the system, the next phase is entered.

  1. timersPhases: This phase performs a timer(setTimeout, setInterval) callback and is controlled by the poll phase.
  2. I/O callbacksPhase: Handles some of the few unexecuted I/O callbacks from the previous cycle.
  3. Idle, preparePhase: Used internally by Nodes only.
  4. pollPhase: Get the new I/O event, where node will block under appropriate conditions.
  5. checkPhase: Perform the setImmediate() callback.
  6. close callbacksPhase: Execute the socket’s close event callback.

There are four macro tasks in NodeJs

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

All four belong to macro queues, but in the browser, you can think of only one macro queue, and all macro-tasks are added to that one macro queue, but in NodeJs, different macro-tasks are placed in different macro queues.

There are two main microtasks in NodeJs

  1. Next Tick Queue: This is where the process.nexttick (callback) callback is placed.
  2. Other Micro Queue: Places Other Micro tasks, such as promises.

In a browser, you can also think of a single microqueue to which all micro-tasks are added, but in NodeJs, different micro-tasks are placed in different microtask queues.

NodeJs is the EventLoop procedure

  1. Synchronous code that executes the global Script.
  2. To execute micro-task tasks, run all tasks in the Next Tick Queue and then all tasks in the Other Micro-Task Queue.
  3. The Event Loop in the browser will select only the first macro task from the macro task queue. The Event Loop will select only the first macro task from the macro task queue. After the macro-task of each stage is completed, start the micro-task, that is, step 2.
  4. Timers Queue -> Step 2 -> I/O Queue -> Step 2 -> Check Queue -> Step 2 -> Timers Queue……
  5. This is the Node Event Loop.

Node 11.x new changes

Node11 is now in the timer phase setTimeout, setInterval… And immediate in the check phase are both modified on Node11 to execute the microtask queue as soon as a task in a phase is executed. It’s all about more convergence with the browser.