Execution order

Ruan Yifeng talks about Event loop

  1. All synchronization tasks are executed on the main thread, forming an execution context stack.
  2. In addition to the main thread, there is a task queue.
  3. Once all synchronous tasks in the execution stack are completed, the system will read the task queue, and the asynchronous tasks in the execution stack will end their waiting state and start execution
  4. The main thread repeats the above three steps over and over again

Personal understanding

In an event poll, there is a main thread, an execution stack, a task queue, and a microtask queue. The code is in the main thread, and when it encounters synchronous code, it executes. If a microtask is encountered, it is put into the microtask queue, and when an asynchronous macro task is encountered, it is put into the macro task queue. When the synchronization task is complete, the system checks whether microtasks exist and clears the microtask queue. At this point, the event polling is complete. Then execute the stack, fetch the asynchronous macro task in the task queue, execute the code inside, repeat the above operation…. Until the code is executed

Microtasks: Process. nextTick, Promise, MutationObserver

Macro tasks: Script, synchronized code are among the macro tasks setTimeout, setInterval, setImmediate, I/O, UI-rendering

Execution stack

The execution stack can be thought of as a stack structure that stores function calls

Process, thread

Thread: A thread is a smaller unit of a process that describes how long it takes to execute an instruction. JS is a single-threaded language

What are the benefits of single thread Js?

Memory saving, more secure rendering

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
   }
   async function async2() {
    console.log('async2 start');
    return new Promise((resolve, reject) = > {
     resolve();
     console.log('async2 promise'); })}console.log('script start');

   setTimeout(function() {
    console.log('setTimeout');
   }, 0);  // Go to the macro task queue
   
   async1();
   new Promise(function(resolve) {
    console.log('promise1');
    resolve();
   }).then(function() { // Microtask queue
    console.log('promise2');
   }).then(function() { // Microtask queue
    console.log('promise3');
   });
   console.log('script end');
   
 // script start, async1 start, async2 start ,async2 promise,promise1,script end,  
 //promise2,promise3,setTimeout
Copy the code

async await

Declaring async before a function means that a Promise object is returned. The value returned by the return statement inside the async function becomes an argument to the then method callback function. That is, writing async is equivalent to a promise that executes resolve(), which must be a success. When async has an await inside it, the contents of the await statement are immediately executed, but the code after the await statement is blocked.

async function async1() {
   console.log('async1 start');
   await async2();
   console.log('async1 end');
  }
Copy the code

(that is, async2 will be executed immediately, but the console.log(‘async1 end’) will block and go to the microtask queue for the next event poll.)

Then jump out of the current function and execute the external synchronization code. When the synchronous code is finished, check the microtask queue in the current asynchronous task. After clearing the microtask queue, execute the macro task queue in the asynchronous task. At this point, the event polling is complete. The next event poll, with setTimeout, goes to the asynchronous macro task, will go to the next event poll, and the console.log(‘async1 end’) is in the microtask queue for this event poll, and will be executed. (as for why the queue of microtasks is polled in this event, it is await, it is actually inside promise.then(), which refers to the use of generator), then go to the next event poll again, and execute setTimeout.