Js_ event loop mechanism, micro task, macro task.

Let’s briefly talk about the event loop mechanism of js today. We all know that javascript is a single-threaded language, and its core is also because of its single thread.
There are many novices who don't know what EventLoop is. According to the Chinese translation, it is an event loop. How does js handle synchronous and asynchronous processing.
In this article, just briefly talk about the single-threaded processing of js, that is, how the synchronous and asynchronous codes go.

1. Synchronous and asynchronous:


All threads have synchronous queues and asynchronous queues,

Immediately executed task queue, these are all synchronous tasks, such as a simple function;

The request interface sends ajax, sends promise, or time timer, etc. These are asynchronous tasks.

2. Task queue-event loop:


Synchronous tasks will be executed immediately and enter the main thread, and asynchronous tasks will be placed in the task queue (Event Queue).Event Queue 单词的意思就是任务队列。

After waiting for the execution of the synchronous code to complete, return, and then put the asynchronous task in the main thread for execution, repeating this cycle, this is the event cycle.也就是先执行同步,返回来按照异步的顺序再次执行
image

Let's see what the following code will print:

console.log('开始111');

setTimeout(function() {

  console.log('setTimeout111');

}, 0);

Promise.resolve().then(function() {

  console.log('promise111');

}).then(function() {

  console.log('promise222');

});

console.log('开始222');

 

Let's guess what the above code will print? We know that the synchronization code must go first, from top to bottom, first print "start 111", and then print "start 222".
The three asynchronous ones in the middle entered the asynchronous queue, waited for the synchronous execution (printed), and then returned to execute asynchronous, so it was printed out last.
Let's put the printed results first, and we'll come back later. Now we insert a knowledge point in the middle:

3. Macro-tasks and micro-tasks (execute micro-tasks first, then macro-tasks):

In the event loop, each loop operation is called tick, and the task processing model of tick is relatively complicated, and there are two words in it: Macro Task (macro task) and Micro Task (micro task).

simply put:

Macro tasks mainly include: setTimeout, setInterval, script (overall code), I/O, UI interaction events, setImmediate (Node.js environment)

Micro tasks mainly include: Promise, MutaionObserver, process.nextTick (Node.js environment)

Norms: Perform micro tasks first, then macro tasks

Then we know that Promise belongs to micro tasks, setTimeout and setInterval belong to macro tasks, execute the micro tasks first, and then execute the macro tasks after the micro tasks are completed. So let's look at this code again:

console.log('开始111');

setTimeout(function() {

  console.log('setTimeout111');

}, 0);

Promise.resolve().then(function() {

  console.log('promise111');

}).then(function() {

  console.log('promise222');

});

console.log('开始222');

Let's analyze it step by step:

1. When encountering a synchronization task, print "Start 111" first.
2. When encountering an asynchronous setTimeout, put it in the queue to wait for execution.
3. When a Promise is encountered, put it in the waiting queue.
4. When encountering a synchronization task, directly print "Start 222".
5. After synchronous execution, return to the code in the execution queue and execute it from top to bottom. If there are macro task setTimeout and micro task Promise, execute the micro task first, and then execute the macro task.

So the order of printing is: start111, start222, promise111, promise222, setTimeout111.

In the same way, let's analyze another code:

console.log('开始111');

setTimeout(function () {

  console.log('timeout111');

});

new Promise(resolve => {

  console.log('promise111');

  resolve();

  setTimeout(() => console.log('timeout222'));

}).then(function () {

  console.log('promise222')

})

console.log('开始222');

 

Analyze it:

1. When encountering a synchronous code, print "Start 111" first.
2. If setTimeout is asynchronous, put it into the queue and wait for execution.
3. When a Promise function is encountered halfway, the function is executed directly, and "promise111" is printed.
4. When setTimeout is encountered, it is asynchronous, put it in the queue, and wait for execution.
5. When encountering a Promise, then waits for a successful return, asynchronously, and puts it into the queue.
6. When encountering synchronization, print "Start 222".
7. After execution, return and execute the codes in the asynchronous queue in order. There is a micro task, after then, so print "promise222", and then execute two macro tasks "timeout111" and "timeout222".

So, the order of printing is: start111, promise111, start222, promise222, timeout111, timeout222 .

Execute the main task first, put the asynchronous task into the circular queue, wait for the main task to be executed, and then execute the asynchronous task in the queue. Asynchronous tasks execute micro-tasks first and then macro-tasks. This cycle has been repeated and executed repeatedly, which is the event cycle mechanism.

Let's do another exercise. If you want to learn, let's learn this knowledge thoroughly.

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')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

First cycle:

  • First print 1
  • The following is setTimeout is an asynchronous task and a macro task, adding a macro task is temporarily recorded as setTimeout1
  • The following is the process microtask added to the microtask queue and recorded as process1
  • The following is the direct resolve(7) in the new Promise, so the then after printing 7 is a microtask and recorded as then1
  • The setTimeout macro task is recorded as setTimeout2

The first cycle prints out 1 7
the current macro task queue: setTimeout1, setTimeout2
the current micro task queue: process1, then1,

Second cycle:

  • Execute all microtasks
  • Execute process1, print out 6
  • Execute then1 and print out 8
  • The microtasks are all executed, and the first macrotask is executed
  • Execute setTimeout1, that is, lines 3-14
  • first prints out 2
  • When encountering a process microtask, record it as process2
  • resolve prints out 4 in new Promise
  • then microtask is recorded as then2

The second cycle is over, and the current printout is 1 7 6 8 2 4
Current macro task queue: setTimeout2
Current micro task queue: process2, then2

The third cycle:

  • Execute all microtasks
  • Execute process2 and print out 3
  • Executing then2 prints out 5
  • Execute the first macro task, that is, execute lines 25 - 36 in the code corresponding to setTimeout2
  • first prints out 9
  • The process microtask is recorded as process3
  • new Promise executes resolve and prints out 11
  • then microtask is recorded as then3

The current printing sequence is: 1 7 6 8 2 4 3 5 9 11 The
current macro task queue is empty
The current micro task queue: process3, then3

Fourth cycle:

  • Execute all microtasks
  • Execute process3 and print out 10
  • Execute then3 to print out 12

End of code execution:
The final printing order is: 1 7 6 8 2 4 3 5 9 11 10 12
(Please note that the event monitoring in the node environment depends on libuv and the front-end environment is not exactly the same, the output order may be wrong)

Guess you like

Origin blog.csdn.net/qq_41916378/article/details/110000022