Creation and execution of a setTimeout

We know that setTimeout is a delay timer, which will delay the execution of the callback function after a specified time. This article will talk about how setTimeout is executed.

First of all, we know that the message queue is used to store macro tasks, and the main thread will take out the tasks in the queue and execute them in sequence. Therefore, in order to ensure that setTimeout can be executed within the specified time, the tasks created by setTimeout will not be added to the message queue. Meanwhile, The browser also maintains another queue called the delay message queue, which is used to store delayed tasks. The task created by setTimeout will be stored there, and it will remember the creation time and delay the execution time.

Then let’s look at specific examples:

setTimeout(function showName() { console.log('showName')},1000)
setTimeout(function showName() { console.log('showName1')},1000) 
console.log('martincai')
Copy the code

The above example executes like this:

  • 1. Execute macro task from message queue (execute first task directly)
  • 2. Run setTimeout. A delay task will be created. The callback function of the delay task is showName
  • 3. Execute console.log(‘martincai’) code
  • 4. Filter all expired tasks from the delay queue (current time >= Launch time + delay time) and execute them in sequence

So we can see that showName and showName1 are executed at the same time because both delayed tasks have expired

Loop source code:

void MainTherad(a){
  for(;;) {// Execute the task in the message queue
    Task task = task_queue.takeTask(a);ProcessTask(task);
    
    // Execute the task in the delay queue
    ProcessDelayTask(a)if(! keep_running)// If the exit flag is set, exit the thread loop directly
        break; }}Copy the code

Deleting a Delayed Task

ClearTimeout is a native method provided under Windows, which is used to delete the delayed task of specific setTimeout. When we define setTimeout, the return value is the unique ID value of the current task. ClearTimeout then takes the ID and looks for the corresponding task in the delay message queue and kicks it out of the queue

A few notes about setTimeout:

  1. SetTimeout will be affected by the execution time of the macro task in the message queue. As can be seen from the above, the task delayed by the message queue will be executed after the execution of the current task in the message queue. Therefore, the execution time of the current task will hinder the execution time of the delayed task of setTimeout
  function showName() {
    setTimeout(function show() {
      console.log('show')},0)
    for (let i = 0; i <= 5000; i++) {}
  }
  showName()
Copy the code

It can be found that setTimeout is not executed around 0ms, and there will be an obvious delay in the middle, because setTimeout will first put the task into the delay message queue when it is executed. After showName is executed, it will search the expired task in the delay queue. Here the setTimeout task will be delayed by showName

  1. SetTimeout nested with a delay of 4ms

Chrome will use nested setTimeout more than 5 layers as a blocking method, and will automatically change the delay timer to at least 4ms on the sixth call to setTimeout

  1. Change setTimeout for inactive pages to at least 1000ms

When the current TAB page is not active, the setTimeout delay is changed to at least 1000ms to reduce performance and power consumption

  1. The delay time has the maximum value

Currently, Chrome, Firefox and other major browsers use 32bit to store latency, so the maximum is 2 ^ 31-1

  setTimeout(() = > {
    console.log(1)},2 ** 31)
Copy the code

The above code executes immediately