Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The implementation principle of setTimeout and its application attention

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains the "setTimeout implementation principle and use attention", the article explains the content is simple and clear, easy to learn and understand, now please follow the editor's train of thought slowly in depth, together to study and learn "setTimeout implementation principle and use attention" bar!

SetTimeout, which is a timer that specifies how many milliseconds a function will execute.

SetTimeout usage

Var timeoutID = setTimeout (function [, delay, arg1, arg2,...]); var timeoutID = setTimeout (function [, delay]); var timeoutID = setTimeout (code [, delay])

The first argument is a function or an executable string (such as alert ('test'), which is not recommended)

The second parameter is the delay milliseconds, optional, the default value is 0.

The third and subsequent arguments are the input parameters of the function.

The return value of setTimeout is a number, which is timeoutID, which can be used to cancel the timer.

Implementation of setTimeout in browser

In the browser rendering process, all tasks running on the main thread need to be added to the message queue first, and then the event loop system executes the tasks in the message queue sequentially.

In addition to the normal message queue in Chrome, there is another message queue (we can call it a delay queue), which maintains a list of tasks that need to be delayed, including timers and tasks within the Chromium that need to be delayed. So when you create a timer through JavaScript, the rendering process adds the callback task for that timer to the delay queue.

Such as a piece of code like this:

Function foo () {console.log ("test")} var timeoutID = setTimeout (foo,100)

When the setTimeout callback function is called through JavaScript, the rendering process will create a callback task, including the callback function foo, current initiation time, delayed execution time, and so on. The simulation code is as follows:

Struct DelayTask {int64 id; CallBackFunction cbf; int start_time; int delay_time;}; DelayTask timerTask; timerTask.cbf = foo; timerTask.start_time = getCurrentTime (); / / get the current time timerTask.delay_time = 100 transaction / set the delayed execution time

After the callback task is created, the task is added to the deferred execution queue. When will this callback task be carried out?

There is a function in the browser that is specifically used to deal with delayed execution tasks, temporarily called ProcessDelayTask. Its main logic is as follows:

Void ProcessTimerTask () {/ / fetch timer tasks that have expired from delayed_incoming_queue / / execute these tasks in turn} TaskQueue task_queue Void ProcessTask (); bool keep_running = true; void MainTherad () {for (;;) {/ / execute the task in the message queue Task task = task_queue.takeTask (); ProcessTask (task); / / execute the task in the delay queue ProcessDelayTask () if (! keep_running) / / if the exit flag is set, exit thread loop break;}} directly

In fact, when the browser has finished processing a task in the message queue, it will begin to execute the ProcessDelayTask function. The ProcessDelayTask function calculates the expired tasks based on the initiation time and delay time, and then executes these expired tasks in turn. Wait for the due task to complete before continuing with the next cycle. In this way, the timer is implemented, and it is also clear from this process that the timer is not necessarily delayed on time.

Matters needing attention

Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community

If the current task is executed for too long, the execution of the expiration timer task will be delayed

When using setTimeout, there are many factors that cause the callback function to execute longer than the expected value, one of which is mentioned above. If the current task takes too long, the task set by the timer will be delayed.

For example, execute a piece of code in a browser and print the execution time:

Function bar () {console.log ('bar') const endTime = Date.now () console.log (' cost time',endTime-startTime)} function foo () {setTimeout (bar, 0); for (let I = 0; I

< 5000; i++) { let i = 5+8+8+8 console.log(i) } } foo() 执行结果如图:

As you can see from the results, the time taken to execute the foo function is 365 milliseconds, which means that the task set through setTimeout is delayed by 365 milliseconds, while the callback delay for setting setTimeout is 0.

2. The this environment in the callback function set with setTimeout does not point to the callback function.

For example, this code:

Var name= 1; var MyObj = {name: 2, test:1, showName: function () {console.log (this.name,this.test);}} setTimeout (MyObj.showName,1000) MyObj.showName () / / output 2 1 / / 1 s followed by 1 undefined

In fact, a careful analysis here, but also very good to understand the direction of this this. According to this, if it is an object call (obj.fn ()), then this points to that object, so MyObj.showName () outputs the value in MyObj. In setTimeout, the input parameter is MyObj.showName. This value is passed in here, which can be understood as:

Const fn = MyObj.showName setTimeout (fn,1000)

From this point of view, in setTimeout, when it is executed, fn is actually executed under window, and the this at this time points to window instead of the original function.

3. There is a problem of nested calls in setTimeout

If there are nested calls to setTimeout, the system will set the minimum execution time interval to 4 milliseconds after more than 5 calls.

We can do a rough test in the browser with the following code:

Let startTime = Date.now () function cb () {const endTime = Date.now () console.log ('cost time',endTime-startTime) startTimestartTime = startTime setTimeout (cb, 0);} setTimeout (cb, 0)

Execution result:

As can be seen from the results, the interval between the first five calls is relatively small, with more than five nested calls, and the minimum interval for each subsequent call is 4 milliseconds (the result of my run, the interval is basically 5ms, taking into account the calculation error of code execution).

The reason for this is that in Chrome, when the timer is called more than 5 times, the system will judge that the function method is blocked. If the calling interval of the timer is less than 4 milliseconds, then the browser will set the time interval for each call to 4 milliseconds. You can take a look at the source code (https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/frame/dom_timer.cc)

Static const int kMaxTimerNestingLevel = 5; / / Chromium uses a minimum timer interval of 4ms. We'd like to go / / lower; however, there are poorly coded websites out there which do / / create CPU-spinning loops. Using 4ms prevents the CPU from / / spinning too busily and provides a balance between CPU spinning and / / the smallest possible interval timer. Static constexpr base::TimeDelta kMinimumInterval = base::TimeDelta::FromMilliseconds (4)

Therefore, some real-time requirements are not suitable to use setTimeout, for example, you use setTimeout to achieve JavaScript animation is not necessarily a good idea.

4. For inactive pages, the minimum interval between setTimeout execution is 1000 milliseconds

If the tag is not the currently active tag, the minimum interval of the timer is 1000 milliseconds in order to optimize the load loss of the background page and reduce power consumption. You should pay attention to this when using the timer.

5. There is a maximum delay execution time

Chrome, Safari, and Firefox all store delay values in 32 bit, and 32bit can only store a maximum of 2147483647 milliseconds, which means that if the delay value set by setTimeout is greater than 2147483647 milliseconds, it will overflow, which causes the timer to be executed immediately. Such as:

Let startTime = Date.now () function foo () {const endTime = Date.now () console.log ('cost time',endTime-startTime) console.log ("test")} var timerID = setTimeout (foo,2147483648); / / will be called to execute immediately

Execution result:

After running, you can see that this code is executed immediately. However, if you change the delay value to something less than 2147483647 milliseconds, there will be no problem at execution time.

Thank you for your reading, the above is the content of "setTimeout implementation principle and use attention". After the study of this article, I believe you have a deeper understanding of the implementation principle and use of setTimeout, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report