In the previous interview article, we discussed a question about macro tasks and micro tasks:

setTimeout(function(){
	 console.log('1')
});
 
new Promise(function(resolve){
	 console.log('2');
     resolve();
}).then(function(){
	console.log('3')
});
 
console.log('4')
Copy the code

What is the order of execution of the above code?

2,4,1,3

I don’t know that js is executed line by line, setTimeout is asynchronous, so I put it first. As you go down, console.log(2) is executed, and.then() is asynchronous and comes after; Off the console. The log (4); Log (1); To the console. The log (3).

But is that really the case? I panicked, so I pasted it into my browser and took a look:

Oh, my God! It’s two, four, three, one! I can’t believe it!

With confusion, I can only go to study the running mechanism of JavaScript!

1. JavaScript

JavaScript is a single-threaded language, meaning that you can only complete one task at a time. If there are multiple tasks to be executed, they must queue up to be executed (the first task is completed, and then the next task is executed).

JavaScript event loop

Since JS is a single thread, it is just like a canteen with only one window. Students need to queue up to order food one by one. Similarly, JS tasks should be executed one by one. This mode is simple to implement, but it is bound to be inefficient as future requirements, transactions, and requests increase. Whenever one task takes a long time to execute, subsequent tasks cannot be executed in that time.

The usual super-hd images that include news are slow to load, so should our pages be stuck until the images are fully displayed? To solve this problem, the JavaScript language divides task execution modes into synchronous and asynchronous:

Synchronous mode: it is a kind of execution mode mentioned above, the latter task waits for the end of the previous task, and then executes, the execution order of the program is consistent with the order of the task, synchronous.

Asynchronous mode: is each task has one or more of the callback function (the callback) to the previous after the task, not to perform a task, after but the callback function, after a task is before the end of a task before execution, so the program execution order the order is not consistent with the task, asynchronous.

The content to be expressed in words:

  • Synchronous and asynchronous tasks go to different execution “places”, synchronous tasks go to the main thread, asynchronous tasks go to the Event Table and register functions.
  • When the specified Event completes, the Event Table moves this function to the Event Queue.
  • If the tasks in the main thread are empty after execution, the Event Queue will read the corresponding function and enter the main thread for execution.
  • This process is repeated over and over again, known as an Event Loop.

With the code expression:

let data = []; $.ajax({url:blog.csdn.net, data:data, success () => {console.log(' sent successfully! '); }}) console.log(' code execution ends ');Copy the code

Here is a simple Ajax request code:

  • Ajax goes into the Event Table and registers the callback functionsuccess.
  • performConsole. log(' end of code execution ').
  • Ajax event completion, callback functionsuccessEnter the Event Queue.
  • The main thread reads the callback function from the Event QueuesuccessAnd executed.

I believe that through the above text and code, you have a preliminary understanding of the order of JS execution. But that’s why some people say 2,4,1,3.

However, there is a trick to the asynchronous queue: setTimeout and promise. Then () are all in the asynchronous queue! Next, talk about the tricks (macro and micro tasks).

Macrotasks and microtasks

Everyone understands it differently, because macro and micro tasks are not standard, but the order of execution is pretty uniform across JS.

Macro task

# The browser Node
Square root Square root
setTimeout Square root Square root
setInterval Square root Square root
setImmediate x Square root
requestAnimationFrame Square root x
Ajax Square root Square root
DOM events Square root Square root

Micro tasks

# The browser Node
process.nextTick x Square root
MutationObserver Square root x
Promise.then catch finally Square root Square root

Macro tasks include:

Process. nextTick varies greatly, different nodes perform different tasks, and standard microtasks are executed earlier than macro tasks

Some people like to play the piano

Let’s look at that interview question again:

SetTimeout (function(){// macro task console.log('1')}); new Promise(function(resolve){ console.log('2'); Resolve (); }). Then (function(){// console.log('3')}); Console. log('4')// Synchronizes the main threadCopy the code

2: indicates the first synchronization

4: indicates the second synchronization, therefore the second

3: asynchronous microtasks, so the third

1: asynchronous macro task, so second

So: 2,4,3,1!

In addition, let’s expand:

SetTimeout (() => {// macro task queue 1 console.log('1'); SetTimeout (() => {console.log('2')}, 1) new Promise(resolve => {resolve() console.log('3')// console.log('4')}). (0) setTimeout () = > {/ / macro task queue 2 console. The log (' 5 ')}, 0) to the console. The log (' 6 ') / / main thread simultaneouslyCopy the code

Console. log(‘6’) >> macro task queue 1, macro task queue 2 bits asynchronous (executed in sequence)

Macro task queue 1: =>

        console.log(‘1’)

        console.log(‘3’)

Console. log(‘4’)// Micro tasks in macro tasks

The remaining tasks are not executed first, as they are macro tasks (console.log(2)) of macro tasks, and will continue to be thrown into the task queue

Macro task queue 2: =>

         console.log(‘5’)

Macro task 3 in macro task queue 1: =>

        console.log(‘2’)

What does this code say?

4. Expand macro and micro tasks

Above a complex problem, partners may wish to think about this complex situation, a set of a how to implement it?

Overall code:

  • 6: the first synchronization main thread, therefore the first

There is no microtask in script code, so execute macro task directly =>

Macro task queue:

  • Macro task queue 1

Task 1: console.log(1)

Task 2: console.log(3)

Microtasks in macro task queue 1: console.log(4)

Macro task queue 3: it is a macro task in macro task queue 1, so it is thrown into the task queue. So at last!

  • Macro task queue 2

        console.log(5)

So what is the output? It’s six, one, three, four, five, two!

After verification, the result is correct!


5, summary

In fact, you only need to know before the expansion, after all, the expansion is really more complex, need a certain understanding ability, he can be three layers, can be four layers…. I don’t believe you will write code like this topic, this is not han batch is what 😆.

Keep these points in mind for macro and micro tasks:

  • Microtasks are executed earlier than macro tasks.
  • If there is a macro task in the macro task, it will not execute the macro task inside, but will be thrown to the back of the task queue, so it will execute last.

This is my share to you, if useful, but also hope you come to a three even support yo ~ ~ ~ thank 🙏 everyone.

Last question:

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')
    })
})
Copy the code

NextTick: process. NextTick: process. NextTick: process