Start with an interview question

This is a classic interview question, the main examination is our protagonist today’s event cycle, we can first carefully taste, write down the answer you think of, continue to read.

Js event loop

First of all, we all know that JS is a single-threaded language, and only one JS statement can be run at most at any runtime moment. But in the actual development, we found that due to various reasons, some program execution will be very time consuming, if only through code from above sequentially, so behind the time consuming process procedure will have been waiting for, when you open a video page, for example, we don’t want to wait for the video is loaded to click play to watch? Obviously the answer is no. At this point, the clever programmer discovered that if the CPU switched js task scheduling at high speed, we could create the appearance of simultaneous task execution. Allows you to watch buffered video clips while buffering them. We call this simple sequential task Synchronous Tasks and the relatively time-consuming wait Tasks Asynchronous Tasks.

In the JS event cycle, we divide asynchronous tasks into macrotasks and microtasks.

  • Macro tasks: setTimeout, setInterval, IO events, etc….
  • Micro tasks: Promise. Then, the process nextTick, MutationObserver

Js executes, js engine will first script top-down parsing, if it is synchronization tasks run in the main thread execution would be put on the stack, if is an asynchronous task is performed in the asynchronous queue, when after the asynchronous task execution, js engines to asynchronous tasks according to the types of asynchronous task callback processing tasks into corresponding macro task queue or micro task queue.

, as shown in the js event loop, at the beginning of each time, js engine will determine whether the current macro task list is empty, if there is a macro will move macro task to the main thread execution stack, and then carry out the tasks of the main thread execution stack finally in check whether there is micro task queue tasks need to be performed, such an event loop is complete.

Return to the topic

Now that we know the loop of events, let’s go back to the interview question.

In the first event loop, the program checks the macro task queue, finds that the queue is empty, enters the main thread stack, and executes a main function:

  1. The function starts by printing outmain start
  2. Then, when the first setTimeout macro task is encountered, setTimeout is put into the asynchronous queue for execution. Since the delay time of setTimeout is 0 (we default to instantaneous completion here, in fact, the minimum delay is close to 4ms), the callback task of the first setTimeout is put into the macro task queue In the column;
  3. Process. nextTick is an instant microtask, put it in an asynchronous queue and put the callback into the microtask after execution.
  4. Then there’s a Promise, which is printed when it’s implementedsecond PromiseThen moves its callback function into the microtask.
  5. Finally print outmain end

At this point, all the tasks of the main thread execution stack in the first event loop are completed, and then the microtask is entered. It is found that there are two tasks in the microtask queue:

  1. Execute the process.nextTick callback and print the nextTick function

  2. Execute the second Promise then function of the last promise. then callback in the code and execute a setTimeout with a delay of 0. Similarly, put the setTimeout callback into the macro task.

    So the cycle of events ends.

The js engine checks the macro task queue and finds that there are two setTimeout tasks. The first setTimeout is placed on the main thread stack in queue order to print the first setTimeout function and the Promise to print the first Promise, puts promise. then on the microtask queue, terminates the main thread execution stack, and then executes the microtask queue to print the first Promise then function, which completes the second event loop.

Finally, the third event loop is executed to check macro tasks and only one setTimeout is left. Print second setTimeout function and all tasks are completed.

So the end result is:

  1. main start
  2. second Promise
  3. main end
  4. next tick function
  5. second Promise then function
  6. first setTimeout function
  7. first Promise
  8. first Promise then function
  9. second setTimeout function

SetTimeout, setInterval

SetTimeout and setInterval put the callback function into the macro task queue of the next round after a delay. Therefore, if the time required to complete the remaining synchronization tasks and micro-tasks is longer than the delay time of setTimeout and setInterval, the delay of the callback function will be triggered. This also explains why the setInterval callback will be fired at any time when the setInterval delay is exceeded.

Finish with an interview question

At the end of the story, we leave a question to ponder, as for the answer……..

async function async1() :Promise<void> {
  console.log('async1 start');
  await async2();
  console.log('async1 end');
}

async function async2() :Promise<void> {
  console.log('async2');
}

console.log('script start');

setTimeout(() = > {
  console.log('setTimeOut');
}, 0);

async1();

new Promise<void> ((resolve) = > {
  console.log('promise1');
  resolve();
}).then(() = > {
  console.log('promise2');
});

console.log('script end');

Copy the code

The last

Thank you for your reading. I hope you have learned something from it. If there is any mistake, please correct it.