As a qualified programmer, you are no stranger to setTimeout. It is a timer that specifies how many milliseconds after a function is executed; It returns the number of a timer that can be manually cleared using clearTimeout.

I won’t repeat here that setTimeout is A macro task, A JavaScript way to perform asynchronous functions, or use it to implement Promises/A+ Promises. Because these are too basic, too simple! Today I’m going to introduce you to setTimeout cold knowledge that you may not know… (The following cases are executed in Chrome, please feel at ease to eat)

Does the setTimeout interval increase by itself?

Have you noticed that when you create a setTimeout and let it run a few milliseconds later, when you open a new page and leave the current TAB inactive, the delay actually becomes 1 second?

Just open your Chrome browser and go into Developer mode, type the following code on the Console, and press Enter:

var timer = setTimeout(function fn() {
    timer = setTimeout(fn, 500)
    console.log(new Date().getSeconds())
}, 500)
Copy the code

The above code creates a loop timer that executes every 500 milliseconds and keeps going. When you execute this code, it will print the current time in seconds in your console, twice per time second, because the interval is set to 500 milliseconds. At this point, you open a new TAB page, leave the TAB page executing the code inactive, and after a few seconds of meditation, witness the miracle. Cut back to the previous page and see what happened to the time seconds printed by the console during that time!

All right, we can clear it out! ClearTimeout (timer) Using setInterval has the same effect.

SetTimeout does not depend on the time I set.

First look at the code:

function fn() {
    setTimeout(() = > {
        console.log('go')},1)}Copy the code

When we execute fn, go will be printed after another millisecond. So let’s change this method.

function fn() {
    for (var i = 0; i < 10000; i++) {
       console.log(i)
    }
    setTimeout(() = > {
        console.log('go')},1)}Copy the code

If we execute the above code again, will go print immediately after 1 millisecond?

If you know it, you can skip it. If you don’t know it or if you don’t know it clearly, I suggest you finish this paragraph. Here we systematically review the knowledge point, as far as possible to tell you clearly why.

As we all know, JavaScript is single threaded in the browser. Some students will have questions here. HTML5 puts forward the Web Worker standard, allowing JavaScript scripts to create multiple threads. Multithreading here consists of one main thread and several child threads, which are completely controlled by the main thread. So we can still think of it as single-threaded.

So what’s unique about single threads? It means everyone has to queue up for everything. This brings up an important concept – message queues.

A message queue is a data structure that holds tasks to be executed. New tasks are added to the tail of the queue, and the main thread circulates to read and execute tasks from the message queue header. Think of it as a conveyor belt of goods, with one person constantly loading goods onto the belt from one end, and another person constantly unloading goods from the conveyor belt at the other end.

Tasks in message queues include render events, user interaction events, script execution events, network request completion, file read/write completion events, timers, and so on. Today we are going to focus on timers. Timers are encapsulated into a macro task by an asynchronous callback function, and then added to the end of the message queue. If there are multiple timers, how is the message queue arranged? You can understand, so some asynchronous execution of tasks are stored in a special message queue, in this special message queue for all asynchronous tasks, we can call it an asynchronous message queue, the asynchronous message queue task will in the main message queue after all the tasks in it again.

This is why setTimeout is not executed after 1 millisecond. Because the “for” loop is still running on the main thread, it’s like a carousel that’s too heavy to get off, and whoever’s behind it is waiting for me.

SetTimeout The minimum nested interval is 4 milliseconds

Above we write a loop timer with setTimeout. Every 500 milliseconds the loop continues. The minimum time that can be set is 4 milliseconds, and if you set it to less than 4 milliseconds, it defaults to 4 milliseconds.

var timer = setTimeout(function a() {
    timer = setTimeout(a, 2)
    console.log(new Date().getMilliseconds())
}, 2)
Copy the code

In fact, the interval will be 2 milliseconds for the first 5 executions and 4 milliseconds for each subsequent invocation. The reason for this is that in Chrome, if the timer is called more than five times nested, the system determines that the function method is blocked. If the timer is called at an interval of less than 4 milliseconds, the browser sets the interval for each call to 4 milliseconds.

The setTimeout delay execution time has the maximum value

Chrome, Safari and Firefox all store latency values in 32 bits, which can only hold up to 2,147,483,647 digits, or 24.8 days. This means that setTimeout overflows if the delay is greater than 2147483647 milliseconds.

function fn() {
    setTimeout(() = > {
        console.log('go')},2147483648)}Copy the code

In the code above, executing the fn function prints immediately.

SetTimeout 1 May not be greater than 0

In order to say that? First look at the code:

function fn() {
    setTimeout(() = > {
        console.log('go')},1)
    
    setTimeout(() = > {
        console.log('on')},0)}Copy the code

In the code above, what is the print order of the fn function? Intuitively, the first function is executed after 1 millisecond, and the second function is executed after 0 millisecond, so it prints on first and then go. But that’s not how it turned out.

conclusion

It can be seen that setTimeout itself is a little bit capricious. If you do not know it well, you should use it as little as possible in the project unless you have to, because it is too confusing.

Finally, an interview question is attached to test whether you understand setTimeout deeply enough.

for (var i = 0; i < 10; i++) {
   setTimeout(() = > {
     console.log(i)
   })
}
Copy the code

What is output from execution above? So how do I get the for loop to print 0 to 9 if I’m only allowed to change the body of the method inside it?

Answer in 5 seconds…..

for (var i = 0; i < 10; i++) {
// setTimeout(() => {
     console.log(i)
// })
}
Copy the code