preface

Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money. An Event Loop is an Event Loop that allows browsers or Nodes to run without blocking.

Before we can learn Event Loop, we need to solve a few problems:

  1. What are synchronous and asynchronous?
  2. JavaScriptIs a single-threaded language, so how do you implement asynchrony?
  3. What is the order in which synchronous and asynchronous tasks are executed?
  4. Do asynchronous tasks have a priority?

Synchronous and asynchronous

Synchronization and asynchrony in the computer world are the opposite of synchronization and asynchrony in our real world. In reality, synchronization means simultaneous, especially simultaneous, such as eating snacks while watching a football match. Asynchronous means not at the same time. But there are certain differences between computer and reality.

Take a chestnut

The weather was cold, I just woke up in the morning and wanted to drink some hot water to warm myself up, but I got up from morning to night every day. I was so tired that I went to sleep when I came back at night. There was no boiling water.

It was too cold in the morning now, so I could not help lying in the bed for a while, and the cleaning time was too tight to wait for the water to boil, so I took advantage of this to wash and clean up myself. After washing, the water opened, drink warm hot water, comfortable ah!

Comfortable end, open the new 996 day, working people set out!

Boiling water and washing are done at the same time. This is asynchrony in computers.

Synchronization in a computer is a continuous action that blocks the next step until the last one is complete. You can’t drink warm hot water until it boils.

Can a single thread be asynchronous?

JavaScript is indeed a single-threaded language, but the browser UI is multithreaded, and asynchronous tasks are implemented using the browser’s thread and JavaScript’s execution mechanism. For example, setTimeout is implemented with the help of a browser timer that triggers a thread’s timing.

Browser thread

  1. GUIThe render thread
    • Draw pages, parse HTML, CSS, build DOM trees and so on
    • Page redrawing and rearrangement
    • Mutually exclusive with JS engine (JS engine blocks page refresh)
  2. JSEngine threads
    • Js script code execution
    • Responsible for executing prepared events, such as timer termination or asynchronous request return with success
    • Mutually exclusive with GUI rendering threads
  3. Event trigger thread
    • When the corresponding event meets the trigger condition, the event is added to the end of the JS task queue
    • Multiple events are queued to join the task queue
  4. Timer trigger thread
    • Timer events that execute asynchrony: setTimeout, setInterval, etc
    • Browser timing is done by this thread, and the event is added to the end of the task queue
  5. HTTPRequest thread
    • Responsible for asynchronous requests
    • When listening for an asynchronous request status change, the thread adds the callback function to the end of the task queue if it exists

Synchronous and asynchronous execution sequence

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

Take a chestnut

  • SetTimeout (cb, 1000) : After 1000ms, the CB will be added to the Event Queue.
  • Ajax (request condition, CB). When the HTTP request is sent successfully, CB is pressed into the Event Queue.

EventLoop executes the process

Event LoopThe execution process is as follows:

Let’s take a look at an example to familiarize ourselves with the process.

// The print result of the following code?
// Prints first for the synchronization task
console.log("first");     
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)
// Prints last for the synchronization task
console.log("last");     
// Read Event Queue prints second
Copy the code

Common Asynchronous Tasks

  • DOMThe event
  • AJAXrequest
  • The timersetTimeoutandsetlnterval
  • ES6thePromise

Priority of asynchronous tasks

Here’s another example:

setTimeout(() = > {
  console.log(1);
}, 1000)
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

Following the above learning: you can easily get the printed result of the case: 2,4,1,3.

The Promise defines the part as synchronous and the callback part as asynchronous

Running the case code on the console returns a somewhat surprising result:

When I saw this result, my first impression was that the setTimeout function 1s fired too slowly and it joined the Event Queue later than promise.then

So I changed the setTimeout callback time to 0(the browser’s minimum trigger time is 4ms), but the result is still changed.

This means that asynchronous tasks in JavaScript have priority.

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. Asynchronous tasks are further divided into micro tasks and macro tasks.

  • history traversalTask (h5History operations)
  • process.nextTick(nodejsAn asynchronous operation in.
  • MutationObserver(h5It was added to the inside for listeningDOMNode changing)

Macro tasks and micro tasks have their own Event queues, namely macro task queues and micro task queues.

Event Loop Indicates the execution process

After learning about macro tasks and micro tasks, let’s learn the execution sequence of macro tasks and micro tasks.

  1. The code starts executing, creating a global call stack,scriptExecute as a macro task
  2. Procedure Synchronous tasks are executed immediately. Asynchronous tasks are registered to the microtask queue and macro task queue respectively based on the type of asynchronous tasks
  3. After the synchronization task is complete, view the microtask queue
    • If there are microtasks, all the microtask queues will be executed (including the new microtasks generated during the execution of the microtasks).
    • If no microtask exists, view the macro task queue and execute the first macro task. After the macro task is executed, view the microtask queue and repeat the preceding steps until the macro task queue is empty

Update the sequence diagram for the Event Loop:

conclusion

On the basis of the above learning, re-analyze the current case:

setTimeout(() = > {
  console.log(1);
}, 1000)
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

The analysis process is shown in the figure below:

The interview questions

At the end of the article, there are some classic interview questions to test your knowledge of Event Loop.

Subject to a

console.log('script start');

setTimeout(() = > {
    console.log('time1');
}, 1 * 2000);

Promise.resolve()
.then(function() {
    console.log('promise1');
}).then(function() {
    console.log('promise2');
});


async function foo() {
    await bar()
    console.log('async1 end')
}
foo()

async function errorFunc () {
    try {
        await Promise.reject('error!!! ')}catch(e) {
        console.log(e)
    }
    console.log('async1');
    return Promise.resolve('async1 success')
}
errorFunc().then(res= > console.log(res))

function bar() {
    console.log('async2 end')}console.log('script end');
Copy the code

Topic 2

setTimeout(() = > {
    console.log(1)},0)

const P = new Promise((resolve, reject) = > {
    console.log(2)
    setTimeout(() = > {
        resolve()
        console.log(3)},0)
})

P.then(() = > {
    console.log(4)})console.log(5)
Copy the code

The title three

var p1 = new Promise(function(resolve, reject){
    resolve("2")})setTimeout(function(){
    console.log("1")},10)

p1.then(function(value){
    console.log(value)
})

setTimeout(function(){
    console.log("3")},0)
Copy the code