JS event loop

JavaScript is known to be a single-threaded scripting language, and if one task takes too long, the next must wait. As a result, if the execution event of a task is too long, the following tasks can not be executed and the page is always loaded. In this way, there are synchronous tasks and asynchronous tasks. Asynchronous tasks are divided into macro tasks and micro tasks

An Event Loop is a mechanism for processing asynchronous tasks to ensure that the browser or Node runs without blocking

Macro task

A Macrotask can be understood as a Macrotask that executes the code on each execution stack (including fetching an event callback from the event queue and placing it on the execution stack each time). The triggering of the event, the non-js part of the event, and the timer can all be classified as macro tasks

To enable orderly execution of Macrotask and DOM tasks within JS, browsers will re-render the page after the completion of one Macrotask execution and before the start of the next Macrotask execution, as follows:

Macrotask – > render – > Macrotask – >…

Common macro tasks include:

SetTimeout setInterval postMessage MessageChannel setImmediate(Node.js)

Micro tasks

A Microtask can be understood as a task that executes immediately after the current Macrotask execution ends. That is, after the current Macrotask, before the next Macrotask, and before rendering.

So it responds faster than setTimeout (Macrotask) because there is no need to wait for rendering. That is, after a Macrotask has been executed, all microTasks created during its execution have been executed (before rendering).

Common microtasks include:

Promise.then object.observe MutaionObserver Process.nexttick (Node.js environment)

Operation mechanism

In an event cycle, each operation is called tick. The task processing model of each tick is complex, but the key steps are as follows:

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

For example

console.log('begin')
/ / macro task
setTimeout(() = > {  
    console.log('setTimeout')},0);
Micro / / task
Promise.resolve().then(() = > {
    console.log('promise');
});
console.log('end');
Copy the code

Begin — > end — > Promise — > setTimeout