preface

The core idea behind the browser execution environment is that only one piece of code can be executed at a time, the so-called single-threaded execution model. Imagine standing in line at a bank counter, everyone entering a line to be called and “processed.” JavaScript, on the other hand, opens only one counter! When it is the turn of a customer (an event), only that customer can be processed.

Take a look at this JavaScript code:

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

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

console.log('script end');
Copy the code

Let’s guess what the output order of this code is.

Event loops and task queues

All tasks can be divided into synchronous tasks and asynchronous tasks, which enter different execution environments respectively. Synchronization tasks are usually directly entered into the main thread and executed immediately. Asynchronous tasks, namely asynchronously executed tasks (such as Ajax network requests, setTimeout timing function, etc.), are all asynchronous tasks, which will be coordinated through the mechanism of task Event Queue.

When the execution of tasks in the main thread is complete, the corresponding task will be read from the Event Queue and pushed to the main thread for execution. The repetition of this process is called an Event Loop.

Event loops usually require at least two task queues: macro task queues and micro task queues. Both queues execute only one task at a time.

The code analysis

1. The whole script enters the main thread as the first macro task, encounters console.log, and prints script start 2. When a setTimeout is encountered, its callback function is dispatched to the macro task Event Queue 3. When a Promise is encountered, its then function is assigned to the microtask Event Queue, named then1, and then it is encountered and assigned to the microtask Event Queue, named then24. When console.log is encountered, print script end

At this point, there are three tasks in the Event Queue:

1. Perform the micro task: Run then1 and output promise1, 2. Perform microtasks: Execute then2 and output promise2, thus emptying all microtasks 3. Execute macro tasks: print setTimeout. The output sequence is script start, script end, promise1, promise2, setTimeout

Here is a question, you can use the above method to do an exercise:

console.log('script start');

setTimeout(function() {
  console.log('timeout1');
}, 10);

new Promise(resolve => {
    console.log('promise1');
    resolve();
    setTimeout(() => console.log('timeout2'), 10);
}).then(function() {
    console.log('then1')
})

console.log('script end');
Copy the code

conclusion

Remember that JavaScript is a single-threaded language and asynchronous operations are placed in an event loop queue waiting for the main execution stack to execute.

reference

Tasks, microtasks, queues and schedules

JavaScript Ninja Secrets 2nd edition Chapter 13 Yagu calendar new events