Lecture
setTimeout
setInterval
setInterval
setTimeout
setTimeout(func, 0)
Almost all implementations of JavaScript have an internal timer scheduler that allows you to set a function call after a specified period of time.
In particular, this feature is supported in browsers and in the Node.JS server.
setTimeout
Syntax:
var timerId = setTimeout(func/code, delay[, arg1, arg2...]) |
Options:
func/code
Function or line of code to execute.
The string is supported for compatibility, it is not recommended to use it.
delay
The delay in milliseconds, 1000 milliseconds, is 1 second.
arg1
, arg2
...
Arguments to pass to the function. Not supported in IE9-.
The function will be executed after the time specified in the delay
parameter.
For example, the following code will trigger an alert('Привет')
in one second:
1 |
function func() { |
2 |
alert( 'Привет' ); |
3 |
} |
4 |
setTimeout(func, 1000); |
If the first argument is a string, the interpreter creates an anonymous function from this string.
That is, such a record works in the same way:
1 |
setTimeout( "alert('Привет')" , 1000); |
The use of strings is not recommended, as they can cause problems when minimizing code, and, in general, the very possibility of using a string is retained only for compatibility.
Instead, use anonymous functions:
1 |
setTimeout( function () { alert( 'Привет' ) }, 1000); |
In all modern browsers, taking into account IE10, setTimeout
allows you to specify function parameters.
The example below displays "Привет, я Вася"
everywhere except IE9:
1 |
function sayHi(who) { |
2 |
alert( "Привет, я " + who); |
3 |
} |
4 |
5 |
setTimeout( sayHi , 1000, "Вася" ); |
... However, in most cases we need the support of the old IE, but it does not allow to specify arguments. Therefore, in order to pass them, they wrap the call into an anonymous function:
1 |
function sayHi(who) { |
2 |
alert( "Привет, я " + who); |
3 |
} |
4 |
5 |
setTimeout( function () { sayHi( 'Вася' ) } , 1000); |
A call via setTimeout
does not pass a this
context.
In particular, calling an object's method via setTimeout
will work in a global context. This may lead to incorrect results.
For example, call user.sayHi()
in one second:
01 |
function User(id) { |
02 |
this .id = id; |
03 |
04 |
this .sayHi = function () { |
05 |
alert( this .id); |
06 |
}; |
07 |
} |
08 |
09 |
var user = new User(12345); |
10 |
11 |
setTimeout(user.sayHi, 1000); // ожидается 12345, но выведет "undefined" |
Since setTimeout
runs the user.sayHi
function in a global context, it will not have access to the object through this
.
In other words, these two calls to setTimeout
do the same thing:
1 |
// (1) одна строка |
2 |
setTimeout(user.sayHi, 1000); |
3 |
4 |
// (2) то же самое в две строки |
5 |
var func = user.sayHi; |
6 |
setTimeout(func, 1000); |
Fortunately, this problem is also easily solved by creating an intermediate function:
01 |
function User(id) { |
02 |
this .id = id; |
03 |
04 |
this .sayHi = function () { |
05 |
alert( this .id); |
06 |
}; |
07 |
} |
08 |
09 |
var user = new User(12345); |
10 |
11 |
setTimeout( function () { |
12 |
user.sayHi(); |
13 |
}, 1000); |
The wrapper function is used to pass arguments across the browser and save the execution context.
In the following chapters we will look at additional ways to bind a function to an object.
The setTimeout
function returns a timerId
that can be used to cancel an action.
Syntax: clearTimeout(timerId)
.
In the following example, we set a timeout and then delete (change your mind). As a result, nothing happens.
1 |
var timerId = setTimeout( function () { alert(1) }, 1000); |
2 |
3 |
clearTimeout(timerId); |
setInterval
The setInterval
method has a syntax similar to setTimeout
.
var timerId = setInterval(func/code, delay[, arg1, arg2...]) |
The meaning of the arguments is the same. But, unlike setTimeout
, it starts the function execution not once, but regularly repeats it after a specified time interval. You can stop execution by calling clearInterval(timerId)
.
The following example at startup will display a message every two seconds, until you click the Stop button:
1 |
< input type = "button" onclick = "clearInterval(timer)" value = "Стоп" > |
2 |
3 |
setInterval
A call to setInterval(функция, задержка)
puts the функцию
to be executed at a specified time interval. But there is a subtlety.
In fact, the pause between calls is less than the specified interval.
For example, take setInterval(function() { func(i++) }, 100)
. It performs func
every 100 ms, increasing the counter value each time.
In the picture below, the red block is the func
execution time. The time between blocks is the time between starts of the function, and it is less than the set delay!
That is, the browser initiates the launch of the function carefully every 100мс
, without taking into account the execution time of the function itself.
It happens that the execution of a function takes more time than the delay. For example, the function is complex, and the delay is small. Or the function contains alert/confirm/prompt
statements that block the flow of execution. In this case, interesting things start.
If the launch of the function is not possible, because the browser is busy, it will be queued and executed as soon as the browser is free.
The image below illustrates what is happening for a function that takes a long time to execute.
The function call initiated by setInterval
is added to the queue and immediately occurs when this becomes possible:
The second launch of the function occurs immediately after the end of the first:
More than once in the queue execution is not set.
If the execution of the function takes more time than several scheduled executions, then it will still stand in the queue once. So there is no “accumulation” of launches.
In the image below, setInterval
tries to execute the function at 200 ms and puts the call in a queue. At 300 ms and 400 ms, the timer wakes up again, but nothing passes.
Let's look at an example of how this works.
The internal timer in Safari / Chrome browsers does not tick during alert/confirm/prompt
. If there are 3 seconds left before the execution, then even when the alert
shown for a minute - the delay remains 3 seconds.
Therefore, the example below is not reproduced in these browsers. Other browsers are fine.
alert
. While the modal window is displayed, the execution of JavaScript is blocked. Wait a bit and click OK.Стоп
button.
1 |
< input type = "button" onclick = "clearInterval(timer)" value = "Стоп" > |
2 |
3 |
The following happens.
alert
window pops up - the execution is blocked and remains blocked all the time while the alert
displayed.
Calling setInterval(функция, задержка)
does not guarantee a real delay between executions.
There are cases when the real delay is more or less than the specified one. In general, not the fact that there will be at least some delay.
setTimeout
In cases when not just regular repetition is necessary, but a delay between starts is required, the re-setting of setTimeout
used each time the function is executed.
Below is an example that issues an alert
at intervals of 2 seconds between them .
01 |
< input type = "button" onclick = "clearTimeout(timer)" value = "Стоп" > |
02 |
03 |
On the timeline, there will be fixed delays between starts. Illustration for 100ms delay:
The browser timer has the lowest possible delay. It varies from approximately zero to 4ms in modern browsers. In older it can be more and reach 15ms.
According to the standard, the minimum delay is 4ms. So there is no difference between setTimeout(..,1)
and setTimeout(..,4)
.
See the minimum resolution "live" by the following example.
In the example below, there are DIV'ы
, each extended by a call to setInterval
with the delay specified in it - from 0ms (top) to 20ms (bottom).
Run it in various browsers, in particular, in Chrome and Firefox. You will surely notice that the first few DIV'ов
are animated at the same speed. This is precisely because the timer does not distinguish too small delays.
Open in new window Open in sandbox
The zero delay setTimeout
and setInterval
behavior has browser features.
setTimeout(.., 0)
is the same as setTimeout(.., 4)
. It is performed less frequently than setTimeout(.. ,2)
. This is a feature of this browser.setInterval(.., 0)
will not work. This concerns setInterval
, i.e. setTimeout(.., 0)
works fine.The example below implements the same animation, but via setTimeout
. If you look at it in various browsers, you can notice the differences from setInterval
.
Open in new window Open in sandbox
In some cases, the delay may not be 4ms, but 30ms or even 1000ms.
setTimeout/setInterval
, even if the tab is inactive.
At the same time, a number of them (Chrome, FF, IE10) reduce the minimum frequency of the timer, to 1 time per second. It turns out that in the “background” tab the timer will work, but rarely.
setInterval
starts will be missed.Conclusion: the 4ms frequency should be oriented, but you should not count.
Let's look at reducing the frequency in action on a small example.
When you click on the button below, setInterval(..., 90)
launched, which lists the time intervals between the last 25 timer triggers. Run it. Go to another tab and return.
Run a repeat at 90 ms intervals
Stop replay
If your browser increases the timeout with background tab execution, you will see extended intervals marked in red.
In addition, you will definitely see that the timer is not perfectly accurate.
The code that is used in the example above and considers the time intervals between calls looks like this:
01 |
var timeMark = new Date; |
02 |
setTimeout( function go() { |
03 |
var diff = new Date - timeMark; |
04 |
05 |
// вывести очередную задержку в консоль вместо страницы |
06 |
console.log(diff); |
07 |
08 |
// запомним время в самом конце, |
09 |
// чтобы измерить задержку именно между вызовами |
10 |
timeMark = new Date; |
11 |
12 |
setTimeout(go, 100); |
13 |
}, 100); |
Zero or short timeouts are also used to break the execution flow of “heavy” scripts.
For example, the script for syntax highlighting should analyze the code, create many color elements for highlighting and add them to the document - on a large file it will take a lot of time.
The browser will first eat 100% of the processor, and then it may indicate that the script runs too long.
In order to avoid this, the complex task is divided into parts, the execution of each part is started at a mini-interval after the previous one, to give the browser time. For example, it is planned to highlight 20 lines every 10ms.
setTimeout(func, 0)
This trick is worthy of entering the annals of JavaScript hacks.
The function is wrapped in setTimeout(func, 0)
if they want to start it after the end of the current script.
The fact is that setTimeout
never performs a function immediately. He only plans its implementation. But the JavaScript interpreter will start performing scheduled functions only after the execution of the current script.
By standard, setTimeout
cannot perform a function with a delay of 0
anyway. As we said before, the delay is usually 4ms. But the main thing here is that the execution in any case will be after the execution of the current code.
For example:
01 |
var result; |
02 |
03 |
function showResult() { |
04 |
alert(result); |
05 |
} |
06 |
07 |
setTimeout(showResult, 0); |
08 |
09 |
result = 2*2; |
10 |
11 |
// выведет 4 |
Later, in the chapter Managing the Processing Order, setTimeout (... 0), we will look at the various uses of this trick when dealing with events.
The setInterval(func, delay)
and setTimeout(func, delay)
methods allow you to run func
regularly / once after a delay
milliseconds.
Both methods return a timer identifier. It is used to stop a call to clearInterval/clearTimeout
.
setInterval |
setTimeout |
|
Timing | There is a call strictly on the timer. If the interpreter is busy, one call is queued.
The execution time of the function is not taken into account, so the time from the end of one run to the beginning of another may be different. |
The recursive setTimeout call is used instead of setInterval where a fixed pause between executions is needed. |
Delay | Minimum delay: 4ms. | Minimum delay: 4ms. |
The minimum delay for these methods in modern browsers is different and ranges from approximately zero to 4 ms. In older browsers, it can reach up to 15ms. | ||
Browser features | In IE, the delay 0 does not work. |
In Opera, zero delay is equivalent to 4ms, the remaining delays are handled accurately, including non-standard 1ms, 2ms and 3ms. |
Comments
To leave a comment
Scripting client side JavaScript, jqvery, BackBone
Terms: Scripting client side JavaScript, jqvery, BackBone