It is well known that people who have learned JS know that JS is a single thread running mechanism, not multithreaded mechanism. So the next thing I want to talk about is how JS executes. I hope it will be helpful to those who have watched this article. JavaScript is executed in the order in which statements appear

Just began to learn to contact JS small cute is not that the implementation of JS code from top to bottom? That’s what I thought at first, that JS was executed line by line.

console.log(a)
var a=1;
var b=2
console.log(b)  
Copy the code

If you look at this code and see if it’s executing from the top down it’s not and you all know that var has variable promotion and the real execution mechanism inside it is

var  a;
console.log(a) ;  //underfind
a=1;
var b;
b=2;
console.log(b);   //b=2
Copy the code

The above code is synchronous and when we encounter synchronous and asynchronous together what is the JS execution mechanism

SetTimeout (function(){console.log(' timer started ')},1000); New Promise(function(resolve){console.log(' execute for loop now '); for(var i = 0; i < 10000; i++){ i == 99 && resolve(); }}). Then (function () {the console. The log (' execution then function! ')}); Console. log(' code execution ends ');Copy the code

If we follow our own thinking when we first started learning but when we open the browser and look at the console the order of output is not

The timer has started, the for loop has started, the then code has finishedCopy the code

but

I'm going to execute the for loop, the code is done, I'm going to execute the then function, and the timer is going to startCopy the code

JS event

Since JS is single threaded, you have to queue one by one, just like when you do accounting. In the same way, JS tasks are executed sequentially

If one task takes too long, the next must also wait. So the problem is, if we want a shopping website, but the product details page has a large image and loads slowly. Do we just load that image all the time, and the rest of the task is waiting for it to load? There is no reason to divide tasks into two categories

  • Synchronization task
  • Asynchronous tasks

When we open the site, the rendering process of the page is a lot of synchronization tasks such as page skeleton and page element rendering. Tasks that take a lot of time, like loading pictures and music, are asynchronous tasks. There are strict text definitions for this part, but the purpose of this article is to thoroughly understand the implementation mechanism with minimal learning cost, so we use a map to illustrate:

Map to express the content of words to express words

  1. 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.

  2. When the specified Event completes, the Event Table moves this function to the Event Queue.

  3. 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.

  4. This process is repeated over and over again, known as an Event Loop.

    Having said all that, the code is much clearer

    let data=[]; $ajax({url:" data: data "; Success :()=>{consolelog(' sent successfully! ')}; }) cosole.log(' code executed ')Copy the code

    You know AJAX is an asynchronous operation so AJAX goes into the Event Table and registers a callback function success

    The console then prints cosole.log(‘ code executed ‘). When the synchronization Event completes, the Success callback enters the Event Queue and outputs the Consolelog (‘ Sent successfully! ‘)}; This code

    setTimeout

SetTimeout is one of the most familiar asynchronous functions. You can perform delayed execution tasks

SetTimeout (() =>{console.log(' delay 5 seconds ')}, 5000)Copy the code

If setTimeout is used a lot, the problem is that it sometimes takes more than 5 seconds to execute the function. Why is this? Let’s start with an example:

SetTimeout (() =>{for(var I =0, I <1000000000, I ++) {I =2* I console.log(I)}},2000)Copy the code

When we look at this code in the browser console, the time to print I is actually more than two seconds.

  1. The timer starts when the setTimeout Event enters the Event Table and is registered
  2. The for loop is executed because the computing time is greater than 2 seconds
  3. After 2 seconds, setTimeout is done, but the for loop is still calculating. You must wait for the for loop to complete before entering the main thread

We know from the above code that the setTimeout function is not output at the time we set

setInterval

SetInterval and setTimeout are twins, but the execution of the latter loop is similar. In terms of execution order, setInterval specifies a period of time for the function to execute, similar to setTimeout

Promise and process. NextTick (the callback)

Next we explore the performance of Promise versus process.nexttick (callback).

The definition and function of Promise is no longer described in this article. Readers who do not know can learn ruan Yifeng teacher’s Promise. Process.nexttick (callback), like node.js’s “setTimeout”, calls the callback function on the next iteration of the event loop.

Let’s get down to business. In addition to generalized synchronous and asynchronous tasks, we have a more detailed definition of tasks:

  • Macro-task: includes the entire code script, setTimeout, and setInterval
  • Micro-task: Promise, process.nexttick

The order of the event loop determines the execution order of the JS code. After entering the overall code (macro task), the first loop begins. Then perform all the microtasks. Then start from the macro task again, find one of the task queues to complete, and then execute all the microtasks. If it sounds a bit convoluted, let’s use the code at the beginning of this article to illustrate:

setTimeout(function() {
    console.log('setTimeout');
})
​
new Promise(function(resolve) {
    console.log('promise');
}).then(function() {
    console.log('then');
})
​
console.log('console');
​
Copy the code

The execution mechanism in JS is top-down

  • The first thing you’ll see is that setTimeout is asynchronous and its callback function is registered and distributed to the macro task Event Queue
  • The new Promise is then immediately executed, and the.then function is distributed to the microtask Event Queue
  • Execute console.log(‘console’) immediately when a synchronization task is encountered;
  • After the first round of synchronous tasks and all, let’s look at what asynchronous tasks (macro tasks, micro tasks) are available
  • The second round starts (only asynchronous). First setTimeout is an asynchronous macro task that is aborted to execute as seen. Then The microtask performs the printing then
  • After the second round of execution, only the macro task in the asynchronous task is left. Run setTimeout and print setTimeout

Let me give you an example to give you an insight

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

You can try it yourself and write the answer below

The first round begins:

  • console.log(‘1’); Synchronize time to print 1

  • SetTimeout is a macro task in asynchrony put it in the Event Queue and we’ll record it as setTimeout 1

  • Process. nextTick is a micro task in async put it in the Event Queue and we log process.nextTick1

  • New Promise direct execution is a synchronization task output 7

  • Then the microtask is put into the Event Queue as.then1

  • The setTimeout macro task is placed in the Event Queue to record setTimeout 2

    Then1 process.nexttick1) then1 process.nexttick1)

Start of the second round

  • Finish the microtasks first

  • Execute process.nextTick1, printing 6.

  • Execute then1 to print 8

    Now execute the macro task

  • SetTimeout 1 The macro task starts

  • Sync console.log(‘2’) is encountered; The output of 2

  • The encounter with process.nextTick is a microtask recorded as process.nextTick2 in the Event Queue the next time it is put in

  • New Promise immediately executes output 4

  • Then is also distributed to the microtask Event Queue, denoted then2.

    The second setTimeout must be queued first because there is a microtask after setTimeout 1 is executed

Start of the third round

  • Microtasks process.nextTick2 and then2 were found

  • Process. nextTick2 output is 3

  • Then2 outputs 5

    The first macro task is complete

Start of the fourth round

  • Now I’m left with setTimeout2
  • console.log(‘9’); Direct output 9
  • Distribute process.nexttick () to the microtask Event Queue. Remember to process3.
  • New Promise just type 11
  • Distribute then to the microtask Event Queue, denoted then3

Start of the fifth round

  • Execute the remaining microtasks to process3 and then3
  • Output 10 of 12

The result is 1,7,6,8,2,4,3,5,9,11,10,12