If the article is helpful to you, your star is the best encouragement for me ~

Brief introduction: talk about promise. Resove, setTimeout, setImmediate, process. NextTick EvenLoop queue in the execution sequence

1. The introduction of questions

An event loop is a loop in which the main thread reads a task from a “task queue”, for example

Case 1:setTimeout(function(){console.log(1)},0); Console. log(2) // Prints 2,1Copy the code

In the example above, we know that the synchronization task in the main thread is executed first, and when the main thread is finished, the task is read from the Event loop, so we print 2 and then 1.

Event loop The sequence of read tasks depends on the read rules of different tasks in the Job queue. Here’s an example:

Example 2:setTimeout(function () {
  console.log(3);
}, 0);

Promise.resolve().then(function() { console.log(2); }); console.log(1); // The output is 1, 2, 3Copy the code

Print 1 first, no problem, because the synchronization task is executed first in the main thread. The problem here is how to define the execution priority of setTimeout and promise. then tasks.

2.Job Queue execution sequence

There are two types of queues in the Job queue: Macro-task and microTask. Let’s take an example of the order of execution. Let’s say

The macro-task queue contains tasks a1, A2, and A3. The micro-task queue contains tasks B1, B2, and B3

First, execute the task at the beginning of the Marco-Task queue, that is, task A1. Then, execute all the tasks in the micro-Task queue, that is, execute *** B1, B2, and B3 *** in sequence. Then clear the tasks in the Micro-Task. The second task in Marco-Task is then executed and the cycle continues.

Now that we know the execution order of the macro-task and micro-Task queues, let’s take a look at the actual tasks contained in the two types of queues in the real world (let’s take Node V8 as an example). In Node V8, the real order of the two types of tasks is as follows:

The macro-task queue actually contains tasks:

Script,setTimeout, setInterval, setImmediate, I/O, UI rendering

The micro-task queue actually contains tasks: Process. nextTick, Promises, Object.observe, MutationObserver

Thus, the execution order we get should be:

Script — > Process. nextTick — >Promises… – > setTimeout – > setInterval – > setImmediate – > I/O – > UI rendering

In ES6, macro-task queues are called ScriptJobs, while micro-tasks are called PromiseJobs

3. Examples of execution sequence in the real environment

(1) the setTimeout and promise

Example 3:setTimeout(function () {
  console.log(3);
}, 0);

Promise.resolve().then(function () {
  console.log(2);
});

console.log(1);

Copy the code

Let’s start with the example in section 1, which follows the following order:

Script — > Promise — >setTimeout corresponds to the following output: 1 — >2————>3

(2) Process. nextTick and Promise, setTimeout

Example 4:setTimeout(function(){console.log(1)},0);

new Promise(function(resolve,reject){
   console.log(2);
   resolve();
}).then(function(){console.log(3)
}).then(function(){console.log(4)});

process.nextTick(function(){console.log(5)}); console.log(6); / / output 2,6,5,3,4,1Copy the code

This example is a little more complicated, but one thing to note here is that when you define a promise, the promise construction part is executed synchronously, so that the problem is solved.

The execution order of the Job queue is as follows:

Script (main program code) — >process.nextTick — > Promise — >setTimeout

I) Body part: The construction part that defines the promise is synchronous, so 2 is printed first, and then 6 is printed from the body part (in the synchronous case, strictly in the order defined)

II) process. NextTick: output 5

III) promise: where the promise part, strictly speaking, is actually a promise. Then part, output is 3,4

IV) setTimeout: output 1

The order of execution is 2 — >6 — >5 — >3 — >4 — >1

(3) More complex examples

setTimeout(function(){console.log(1)},0);

new Promise(function(resolve,reject){
   console.log(2);
   setTimeout(function(){resolve()},0)
}).then(function(){console.log(3)
}).then(function(){console.log(4)});

process.nextTick(function(){console.log(5)}); console.log(6); // Outputs 2, 6, 5, 1, 3, 4Copy the code

The difference between this case and our example in (2) is that there is no synchronous resolve in the construction of the promise. Therefore, the promise. Then does not exist in the current execution queue, and only the then method will exist when the promise is transferred from pending to resolve. Resolve is done in a setTimout time, so 3,4 is output.