Understand how JS works

How often do you get confused when you see code output like the following in a variety of interview questions? It doesn’t matter. Let’s digest him together this time.

console.log('script start');

new Promist(function(resolve) {
  console.log('1');
  resolve();
}).then(functionn() {
  console.log('2');
})

setTimeout(function() {
  console.log('3');
},0)
console.log('script end');
Copy the code

About the js

Javascript is known to be a single-threaded language. However, if we encounter a code such as setTimeout, we will not be silly to wait, which leads to today’s main Event Loop (i.e. Event Loop);

About the Event Loop

Let’s start with a demo:

console.log('1');
setTimeout(function() {
  console.log('2');
},1000)
console.log('3');
Copy the code

For students who are new to js, it is probably the same as when I first knew js. It is natural to think that 1,2,3 will be output in code order. When we confidently put the code on the console, the results are not what we expected.

We usually divide JS into two types: synchronous and asynchronous tasks. The setTimeout above is one kind of asynchrony. When the browser encounters an asynchronous Task, it will put it into the Task queue (Task Queen) and wait for the execution of the synchronous Task in the main thread, which also ensures that the code will not block.

When setTimeout is executed, the callback function will be put into the task queue. After the main thread outputs 3, the event queue will push the task into the stack after it gets the task and execute output 2.

Macrotasks and Microtasks

Common asynchronous tasks include setTimeout, setInterval, promise.then and so on. Let’s look at another demo:

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

According to the above, we confidently wrote down our answers: 1,5,2,3,4. And then we put the code on the console and we said, well, smack in the face. Macrotask and Microtask.

Common macro tasks and microtasks include: MacroTask: setTimeout, setInterval, setImmediate, I/O, UI rendering MicroTask: process.nextTick, Promise.then

First, promise itself is a synchronous task, and its callbacks, then,catch,finally, are asynchronous tasks. If you don’t know anything about promises, click here to learn about them.

Let’s look at the results of the above code: 1,3,5,4,2. As you can see, the asynchronous task of the Promise function code takes precedence over the 0 delay of setTimeout. For this reason, asynchronous tasks are divided into macro tasks and micro tasks. During the main thread execution, the setTimeout callback is placed in the macro task queue, and the promise callback is placed in the microtask queue.

The relationship between event loops, macro tasks and micro tasks is shown in the figure below:

The process of the event loop can be summarized as follows: 1. Execute the main thread first, and add the asynchronous task to the corresponding macro or micro task queue. 2. After the main thread is executed, view the microtask queue and perform the tasks in sequence. 3. After micro task queue to empty, check the macro task queue, a row in front of a macro missions, after each perform a macro task, will see a small task queue, if micro tasks to be performed, will first micro task queue, after the completion of all the micro task execution in the perform under a macro task, so on.

From this process, we can know: 1 -> When setTimeout is encountered, put it into the macro task queue -> When promise is encountered, output 3, put its callback into the microtask queue -> Continue to execute the output 5 -> The main thread finishes running, check the microtask queue, Execute promise’s callback then, output 4 -> microtask queue emptying, execute macro task, output 2 -> end.

About async and await

Now that we have a general understanding of the mechanics of event loops, how do promise based async and await perform? What are async and await? Async means that there is an asynchronous operation in a function, and await means that the following expression needs to wait for the result. Poke this to see async and await parsing in detail

Here’s another demo:

console.log(1);
setTimeout(() => {
  console.log(2)
},0)
fn();
async function fn () {
  console.log(3);
  await fn1();
  console.log(4);
}

async function fn1 () {
  console.log(5);
}
console.log(6);
Copy the code

So in this case, the execution of await has two results: it is or is not a Promise object.

When waiting for something other than a Promise object, await blocks the code below, executing the synchronous code outside async and then executing the previously blocked code inside the async function.

When waiting for the Promise object, the following code will also be blocked. The synchronous code outside async will be executed first, and the previously blocked code will be executed after the Promise object state is fulfilled.

“Await” is a Promise. When an await is performed, a microtask is added to the microtask queue. The microtask executes the blocked code after the await.

So the correct output would be: 1,3,5,6,4,2.

reference

  • Learn the Event Loop once
  • 【THE LAST TIME】 Thoroughly understand JavaScript execution mechanics
  • Understand the cycle of events