Home  >  Article  >  Web Front-end  >  Detailed explanation of JavaScript event loop mechanism - Lecture 2

Detailed explanation of JavaScript event loop mechanism - Lecture 2

韦小宝
韦小宝Original
2018-03-07 15:26:321834browse

Let’s continue to talk about the event loop mechanism in JavaScript. The first lecture on the JavaScript event loop mechanism is not finished. Let’s continue to talk about the JavaScript event loop mechanism. Continue reading this article!

In the last article, I gave a general introduction to the JavaScript event loop mechanism, but in the end I was left with a piece of code and several questions.

Let’s start with this code first

(function test() {
    setTimeout(function() {console.log(4)}, 0);
    new Promise(function executor(resolve) {
        console.log(1);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(2);
    }).then(function() {
        console.log(5);
    });
    console.log(3);
})()

In this code, setTimeout and Promise are both called task sources, and callback functions from different task sources will be put into different task queues.

The callback function of setTimeout is put into the task queue of setTimeout. For Promise, its callback function is not the executor function passed in, but the parameters in its asynchronously executed then method, which are put into the Promise's task queue. In other words, the first parameter of Promise will not be put into the Promise task queue, but will be executed in the current queue.

The task queues of setTimeout and Promise are called macro-task (macro task). Of course, as we think, there are also micro-task (micro task).

  1. macro-task includes: script (overall code), setTimeout, setInterval, setImmediate, I/O, UI rendering.

  2. micro-task includes: process.nextTick, Promises, Object.observe, MutationObserver

The above setImmediate and process.nextTick are Node The API in .JS is not available in the browser. This is just an example. There is no need to worry about how it is implemented.

The order of the event loop is to start the first loop from script, then the global context enters the function call stack. When encountering a macro-task, it is handed over to the module that handles it. After processing, the callback function is put into the macro. In the -task queue, when encountering a micro-task, its callback function is also put into the micro-task queue. Until the function call stack is cleared and only the global execution context is left, all micro-tasks start to be executed. After all executable micro-tasks have been executed. The loop executes a task queue in the macro-task again, and then executes all micro-tasks after execution, and the loop continues like this.

Analysis of the execution process

The following analysis ideas go into the core according to what Mr. Bo wrote before, and explain in detail the events in the event loop mechanism. Analyze ideas.

Use the previous chestnut as the object of analysis to analyze how the event loop mechanism executes the code

(function test() {
    setTimeout(function() {console.log(4)}, 0);
    new Promise(function executor(resolve) {
        console.log(1);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(2);
    }).then(function() {
        console.log(5);
    });
    console.log(3);
})()

Pay attention to the setTimeout task team and the final function call in all the figures below What is stored in the stack are the callback functions of setTimeout, not the entire setTimeouttimer.

Detailed explanation of JavaScript event loop mechanism - Lecture 2

#1. First, the script task source is executed first, and the global context is pushed onto the stack.

Detailed explanation of JavaScript event loop mechanism - Lecture 2

#2. When the script task source code encounters setTimeout during execution, as a macro-task, it puts its callback function into its own queue.

Detailed explanation of JavaScript event loop mechanism - Lecture 2

#3. The code of the script task source encounters a Promise instance during execution. The first parameter in the Promiseconstructor is that the current task will not be put into the queue when it is executed directly, so 1 is output at this time.

Detailed explanation of JavaScript event loop mechanism - Lecture 2

Detailed explanation of JavaScript event loop mechanism - Lecture 2

4. When encountering the resolve function in for loop, the function is pushed into the stack and then popped out. When the Promise's status becomes Fulfilled. The code then executes and encounters console.log(2), which outputs 2.

Detailed explanation of JavaScript event loop mechanism - Lecture 2

#5. Then execute, the code encounters the then method, and its callback function is pushed onto the stack as a micro-task and enters the Promise task queue.

Detailed explanation of JavaScript event loop mechanism - Lecture 2

#6. The code is then executed. At this time, console.log(3) is encountered and 3 is output.

Detailed explanation of JavaScript event loop mechanism - Lecture 2Detailed explanation of JavaScript event loop mechanism - Lecture 2

7.输出3之后第一个宏任务script的代码执行完毕,这时候开始开始执行所有在队列之中的micro-task。then的回调函数入栈执行完毕之后出栈,这时候输出5

Detailed explanation of JavaScript event loop mechanism - Lecture 2

8.这时候所有的micro-task执行完毕,第一轮循环结束。第二轮循环从setTimeout的任务队列开始,setTimeout的回调函数入栈执行完毕之后出栈,此时输出4。

总结

总的来说就是:

1、不同的任务会放进不同的任务队列之中。

2、先执行macro-task,等到函数调用栈清空之后再执行所有在队列之中的micro-task。

3、等到所有micro-task执行完之后再从macro-task中的一个任务队列开始执行,就这样一直循环。

4、当有多个macro-task(micro-task)队列时,事件循环的顺序是按上文macro-task(micro-task)的分类中书写的顺序执行的。

测试

说到这里,我们应该都明白了,下面是一个复杂的代码段(改自深入核心,详解事件循环机制),里面有混杂着的micro-task和macro-task,自己画图试试流程哇,然后再用node执行看看输出的顺序是否一致。

console.log(&#39;golb1&#39;);
setImmediate(function() {
    console.log(&#39;immediate1&#39;);
    process.nextTick(function() {
        console.log(&#39;immediate1_nextTick&#39;);
    })
    new Promise(function(resolve) {
        console.log(&#39;immediate1_promise&#39;);
        resolve();
    }).then(function() {
        console.log(&#39;immediate1_then&#39;)
    })
})
setTimeout(function() {
    console.log(&#39;timeout1&#39;);
    process.nextTick(function() {
        console.log(&#39;timeout1_nextTick&#39;);
    })
    new Promise(function(resolve) {
        console.log(&#39;timeout1_promise&#39;);
        resolve();
    }).then(function() {
        console.log(&#39;timeout1_then&#39;)
    })
    setTimeout(function() {
    	console.log(&#39;timeout1_timeout1&#39;);
    process.nextTick(function() {
        console.log(&#39;timeout1_timeout1_nextTick&#39;);
    })
    setImmediate(function() {
    	console.log(&#39;timeout1_setImmediate1&#39;);
    })
    });
})
new Promise(function(resolve) {
    console.log(&#39;glob1_promise&#39;);
    resolve();
}).then(function() {
    console.log(&#39;glob1_then&#39;)
})
process.nextTick(function() {
    console.log(&#39;glob1_nextTick&#39;);
})

讲到这里我们的细说JavaScript事件循环机制也就正式讲完了,看不懂了两篇结合起来看看,练练即可!

先看看我吧:

细说JavaScript事件循环机制-第一讲

The above is the detailed content of Detailed explanation of JavaScript event loop mechanism - Lecture 2. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn