Learning JavaScript execution mechanism can better understand the sequence of JavaScript code execution, and then better understand the asynchronous mode of JavaScript.

An overview of the

When I first started learning JavaScript, I often had two problems:

  • JavaScriptIs a single-threaded language, so how do you implement asynchronous tasks?
  • What is the order in which synchronous and asynchronous tasks are executed?

Summarize these two questions with a common interview question:

// The print result of the following code?
console.log("first");
setTimeout(() = > {
  console.log("second");
},0)
console.log("last");
Copy the code

Can a single thread be asynchronous?

To address the first problem, JavaScript is indeed a single-threaded language, but the browser UI is multi-threaded, and asynchronous tasks are mostly implemented through the browser and JavaScript execution mechanisms. For example, setTimeout is implemented using the timing functionality of a browser’s timed trigger.

The main child threads of the browser: GUI thread, JS engine thread, event trigger thread, timing trigger thread, asynchronous HTTP request thread

The execution order of JavaScript comes to the heart of this article: the Event Loop.

To understand the Event Loop

Event Loopprocess

  • JavaScriptTasks are divided into synchronous tasks and asynchronous tasks. Synchronous tasks enter the main line, and asynchronous tasks enter firstEvent TableRegister the callback function.
  • When asynchronous taskTrigger condition satisfiedTo change the callback function fromEvent TablePush theEvent QueueIn the.
  • When the synchronization task in the main thread is complete, the system will goEvent QueueRead the asynchronous callback function in.
  • Whenever the main line is open, it’s thereEvent QueueThe process of reading fetch calls is calledEvent Loop.

For example, setTimeout(cb, 1000). After 1000ms, cb will be pressed into the Event Queue. Another example is Ajax (request condition, CB), where when an HTTP request is sent successfully, CB is pushed into the Event Queue.

Which asynchronous tasks will enterEvent Queue?

  • DOMThe event
  • AJAXrequest
  • The timersetTimeoutandsetlnterval
  • ES6thePromise

Case analysis

After learning Event Loop, the case results in the introduction can be easily obtained, and the printing sequence is first,last and second. Let’s break it down:

// The print result of the following code?
console.log("first");     // Prints first for the synchronization task
setTimeout(() = > {        
                          // the asynchronous task is pressed to the Event Table for 4ms. Then the cb task is pressed to the Event Queue
  console.log("second");
},0)
console.log("last");      // Prints last for the synchronization task
                          // Read Event Queue prints second
Copy the code

The advanced

Do you really think you understand JavaScript execution at all? Let’s take a look at an example

setTimeout(() = > {
  console.log(1);
}, 0)
new Promise(function(resolve){
    console.log(2);
    for(var i = 0; i < 10000; i++){
        i == 99 && resolve();
    }
}).then(function(){
    console.log(3)});console.log(4)
Copy the code

After basic learning of JavaScript execution mechanisms, you can easily get the printed result of the case: 2,4,1,3. Run the case code on the console and the result looks like this:

Little head big wonder

Why is the Promise callback executed first and then the Promise callback? The minimum triggering time of setTimeout is 4ms. Does it mean that setTimeout meets the triggering condition before Promise meets the triggering condition? That’s easy. Let’s do a test that extends the time that the Promise in the above case triggers the callback.

setTimeout(() = > {
  console.log(1);
}, 0)
new Promise(function(resolve){
    console.log(2);
    // Increase the loop
    // The native test of 100000000 loops is about 240ms
    for(var i = 0; i < 100000000; i++){
        i == 99999999 && resolve();
    }
}).then(function(){
    console.log(3)});console.log(4)

// Run result 2 4 3 1
Copy the code

It turns out that the Promise callback is still before setTimeout, indicating that the JavaScript mechanism is not fully understood.

Macro and micro tasks

In addition to broadly dividing tasks into synchronous and asynchronous tasks, JavaScript also makes a more detailed division of asynchronous tasks.

NextTick MutationObserver (h5) History Traversal task (h5 history traversal task) process.nexttick (nodeJS asynchronous operation) MutationObserver (H5)

Different tasks will enter the corresponding Event Queue. The execution order of the Event Loop changes as the asynchronous tasks are divided in more detail. (See below for details)

When the main thread is empty, the script macrotask is finished, and the main thread will go to the microtask Event Queue for reading, and then go to macrotask to read the next macrotask, repeating the above process.

Case Study 2

Now let’s go back to case two