setInterval 0 does not work in IE8 - javascript

I have a method changeColor that updates the CSS on some elements in my HTML.
I also have a timer that controls this being applied i.e:
var timer = setInterval(changeColor,0);
The problem i'm facing is using that time interval of 0 results in the changeColor method not being run, however if i change it something minimal like:
var timer = setInterval(changeCalendarColor,1);
it works.
Now i'd be happy to use this however in IE8 this causes a slight delay in the colors appearing.
Any ideas on how to resolve this?
Thanks.

The setInterval function takes a function to call and a delay in milliseconds. You cannot have a delay of 0 milliseconds; there is a minimum delay in place (which according to the specs is 4ms). Take a look at the documentation for more.
// To call a function every second:
var timer = setInterval(myFunction, 1000);
// This doesn't throw an error as the 0 is being overridden by a default minimum:
var timer = setInterval(myFunction, 0);
If you want to call the function initially and ALSO every second after that, you should call the function when you set the interval:
var timer = setInterval(myFunction, 1000);
myFunction();
Here's what the Mozilla docs say about the minimum delay:
"In fact, 4ms is specified by the HTML5 spec and is consistent across browsers released in 2010 and onward. Prior to (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), the minimum timeout value for nested timeouts was 10 ms."
Regarding the slowness on IE8, the setInterval "lag" is probably being caused by IE8 being too slow to keep up with what the function is trying to do. At each time interval, the function is called, but IE8 is queue is being overloaded as a result -- to the point that IE8 can't keep up. Increasing the delay would mask this issue I'd imagine.
As Vasile says on this Google Code forum:
"When a new call is triggered if the previous call is not ended then the new call is queued and will wait for it's time to be executed; and here is the problem... (the timer will slow down when the queue will grow and the performance will go down over time)"
Note that this is a common problem for low delays in IE8; check this post for more on this specific issue.
Also, a quick point to note about setInterval delays is that inactive tabs are occasionally treated differently:
"In (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) and Chrome 11, timeouts are clamped to firing no more often than once per second (1000ms) in inactive tabs..."
See this related SO post for more.

Related

setTimeout runs function immediately

I am trying to use 'setTimeout' to run 'window.open' function after certain period of time. If I calculate the time difference with the parent's property and then use the output for 'setTimeout', the 'window.open' function runs immediately. However, if I just give a number to the variable 'diffms', it works fine.
I am using react and how can I fix this problem?
// const diffms = 10000;
const diffms = moment(this.props.schedule.time).diff(moment());
setTimeout(() => {
window.open("https://www.google.com");
}, diffms);
SetTimeout has Maximum Delay Value
Browsers including Internet Explorer, Chrome, Safari, and Firefox store the delay as a 32-bit signed integer internally.
This causes an integer overflow when using delays larger than 2,147,483,647 ms (about 24.8 days), resulting in the timeout being executed immediately.
Please check more details here:
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#:~:text=Maximum%20delay%20value&text=This%20causes%20an%20integer%20overflow,the%20timeout%20being%20executed%20immediately.

Can't understand the minimal timeout value in `setTimeout()`

I see in some question What is minimum millisecond value of setTimeout? people talk about the "minimal timeout of setTimeout", but I can't really understand it.
It says the minimal timeout value in HTML5 spec is 4ms, so I think, if I run following code in browsers (say Chrome):
setTimeout(function() { console.log("333"); }, 3);
setTimeout(function() { console.log("222"); }, 2);
setTimeout(function() { console.log("111"); }, 1);
setTimeout(function() { console.log("000"); }, 0);
the output should be:
333
222
111
000
But actually it is:
111
000
222
333
Seems like they still be run according to the specified timeout even if they are less than 4 (expect the 0 and 1)
How should I understand the value 4ms?
The limit of 4 ms is specified by the HTML5 spec and is consistent across browsers released in 2010 and onward.
http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#timers
To implement a 0 ms timeout in a modern browser, you can use window.postMessage()
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
More info
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop#Event_loop
After reading the recommended articles (thanks to #Rayon and #rafaelcastrocouto), and also this one:
http://www.adequatelygood.com/Minimum-Timer-Intervals-in-JavaScript.html
I realise that maybe I misunderstood the meaning of "minimal" delay value.
The specified timeout in setTimeout has two meanings:
The function will run when or after specified timeout (not before that)
The order will be decided by the value of the specified timeout, the smaller the earlier (and in some platform, 0 is considered the same as 1), and first added will be earlier if they have the same timeout
We don't need to concern the "minimal" delay value (e.g. 4ms) in this layer.
Then the tasks will be executed by the Javascript runtime. The runtime will take the tasks from the event queue one by one (also check if the timeout is OK), and execute them. But for some performance issue, the runtime can't really run the next task immediately after the previous one finished, there might be a tiny delay(according to different runtime implementations), and in HTML5 spec, the delay should be >= 4ms (it was 10ms in earlier browsers)

Stopwatch not working, it's going way too faster

As I was looking for a simple Stopwatch implementation in JS, I found this code http://codepen.io/_Billy_Brown/pen/dbJeh/
The problem is that it's not working fine, the clock go way too fast. I got 30 seconds on the screen when i got only 23 seconds on my watch.
And I don't understand why. The timer function is called every millisecond and should be updating the time correctly.
setInterval(this.timer, 1);
Is the problem coming from the browser or from the JS code.
Thanks in advance.
The timers in Javascript doesn't have millisecond precision.
There is a minimum time for the interval, which differs depending on the browser and browser version. Typical minimums are 4 ms for recent browsers and 10 ms for a little older browsers.
Also, you can't rely on the callback being called at exact the time that you specify. Javascript is single threaded, which means that if some other code is running when the timer triggers a tick, it has to wait until that other code finishes.
In fact the code you gave is imitating time flow, but it is not synchronized with system time.
Every millisecond it just invokes the function this.time, which performs recounting of millis, seconds and so on
without getting native system time, but just adding 1 to variable representing "imaginary milliseconds".
So we can say that resulting pseudo-time you see depends on your CPU, browser and who knows what else.
On our modern fantastically fast computers the body of this.time function is being executed faster than millisecond (wondering what would happen on Pentium 2 with IE5 on board).
Anyhow there is no chance for the this.time to be executed exactly in particular fixed period on all computers and browsers.
The simplest correct way to show the time passed since startpoint according to the system time is:
<body>
<script>
var startTime = new Date() // assume this initialization to be start point
function getTimeSinceStart()
{
var millisSinceStart = new Date() - startTime
, millis = millisSinceStart % 1000
, seconds = Math.floor(millisSinceStart / 1000)
return [seconds, millis].join( ':' )
}
(function loop()
{
document.title = getTimeSinceStart() // look on the top of page
setTimeout( loop, 10 )
}())
</script>
</body>
P.S. What #Guffa says in his answer is correct (generally for js in browsers), but in this case it does not matter and not affect the problem

setTimeout with shorter timeout vs longer timeout

I am trying to debate whether this is a good method of handling timers in Javascript. I am using Angular, but the concept is the same as using setTimeout instead of the $timeout function Angular provides.
Old method:
$scope.timer=$scope.doTiming();
$scope.timeRemaining=30; //30 second timer;
$scope.doTiming=function(){
return $timeout(function(){
$scope.timeRemaining=$scope.timeRemaining-1;
if($scope.timeRemaining<=0){
$scope.disabledEntry=true;
$scope.submitData();
}else{
$scope.timer=$scope.doTiming();
}
},1000);
};
Time elapsed on a 30 timer: 30.050 seconds
New Method:
var startTime=new Date().getTime, delta; //new: get current time
$scope.timeRemaining=30;
$scope.timer=$scope.doTiming();
$scope.doTiming=function(){
return $timeout(function(){
delta=(new Date().getTime())-startTime; //new: get delta from start time
$scope.timeRemaining=$scope.timeRemaining-(delta/1000); //new: subtract by delta
if($scope.timeRemaining<=0){
$scope.disabledEntry=true;
$scope.submitData();
}else{
$scope.timer=$scope.doTiming();
}
},1);
};
Time elapsed on a 30 timer: 30.002 seconds
Major difference is that the old way looped every second, and ticked down the timer. The new way loops constantly very quickly and measures the time based on the change in time from the start, so it has the potential to be more accurate. I am wondering if this is reasonable or not? Is this type of instant loop going to cause issues on older computers? Should I maybe use the new way with a timer of 100 instead of 1? Thoughts?
EDIT
The new way is preferable to me for reasons associated with slowed timeouts: Chrome: timeouts/interval suspended in background tabs?
In my opinion, you should do as many "timeouts" as necessary, but as few as possible. In other words, if you need to update a timer every second, trigger a timeout every second. Nobody will be able to notice a 50ms delay in a timer update (nor would anyone care), so I think it is not worth bothering the browser with additional JavaScript cycles which, for example. might be better spent updating some animation.
I can't think of a reason why this wouldn't apply to the delta-time approach as well. Worst-case scenario would be that a tab goes to the background right after a one second timeout was triggered. When the user comes back to the tab, it would then take about a second until the timer would refresh, and in that interval the user would still see the timer value from when he made the tab inactive. If that is acceptable for your use case, I wouldn't worry about increasing the interval at all :)

setTimeout or setInterval?

As far as I can tell, these two pieces of javascript behave the same way:
Option A:
function myTimeoutFunction()
{
doStuff();
setTimeout(myTimeoutFunction, 1000);
}
myTimeoutFunction();
Option B:
function myTimeoutFunction()
{
doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);
Is there any difference between using setTimeout and setInterval?
They essentially try to do the same thing, but the setInterval approach will be more accurate than the setTimeout approach, since setTimeout waits 1000ms, runs the function and then sets another timeout. So the wait period is actually a bit more than 1000ms (or a lot more if your function takes a long time to execute).
Although one might think that setInterval will execute exactly every 1000ms, it is important to note that setInterval will also delay, since JavaScript isn't a multi-threaded language, which means that - if there are other parts of the script running - the interval will have to wait for that to finish.
In this Fiddle, you can clearly see that the timeout will fall behind, while the interval is almost all the time at almost 1 call/second (which the script is trying to do). If you change the speed variable at the top to something small like 20 (meaning it will try to run 50 times per second), the interval will never quite reach an average of 50 iterations per second.
The delay is almost always negligible, but if you're programming something really precise, you should go for a self-adjusting timer (which essentially is a timeout-based timer that constantly adjusts itself for the delay it's created)
Is there any difference?
Yes. A Timeout executes a certain amount of time after setTimeout() is called; an Interval executes a certain amount of time after the previous interval fired.
You will notice the difference if your doStuff() function takes a while to execute. For example, if we represent a call to setTimeout/setInterval with ., a firing of the timeout/interval with * and JavaScript code execution with [-----], the timelines look like:
Timeout:
. * . * . * . * .
[--] [--] [--] [--]
Interval:
. * * * * * *
[--] [--] [--] [--] [--] [--]
The next complication is if an interval fires whilst JavaScript is already busy doing something (such as handling a previous interval). In this case, the interval is remembered, and happens as soon as the previous handler finishes and returns control to the browser. So for example for a doStuff() process that is sometimes short ([-]) and sometimes long ([-----]):
. * * • * • * *
[-] [-----][-][-----][-][-] [-]
• represents an interval firing that couldn't execute its code straight away, and was made pending instead.
So intervals try to ‘catch up’ to get back on schedule. But, they don't queue one on top of each other: there can only ever be one execution pending per interval. (If they all queued up, the browser would be left with an ever-expanding list of outstanding executions!)
. * • • x • • x
[------][------][------][------]
x represents an interval firing that couldn't execute or be made pending, so instead was discarded.
If your doStuff() function habitually takes longer to execute than the interval that is set for it, the browser will eat 100% CPU trying to service it, and may become less responsive.
Which do you use and why?
Chained-Timeout gives a guaranteed slot of free time to the browser; Interval tries to ensure the function it is running executes as close as possible to its scheduled times, at the expense of browser UI availability.
I would consider an interval for one-off animations I wanted to be as smooth as possible, whilst chained timeouts are more polite for ongoing animations that would take place all the time whilst the page is loaded. For less demanding uses (such as a trivial updater firing every 30 seconds or something), you can safely use either.
In terms of browser compatibility, setTimeout predates setInterval, but all browsers you will meet today support both. The last straggler for many years was IE Mobile in WinMo <6.5, but hopefully that too is now behind us.
setInterval()
setInterval() is a time interval based code execution method that has the native ability to repeatedly run a specified script when the interval is reached. It should not be nested into its callback function by the script author to make it loop, since it loops by default. It will keep firing at the interval unless you call clearInterval().
If you want to loop code for animations or on a clock tick, then use setInterval().
function doStuff() {
alert("run your code here when time interval is reached");
}
var myTimer = setInterval(doStuff, 5000);
setTimeout()
setTimeout() is a time based code execution method that will execute a script only one time when the interval is reached. It will not repeat again unless you gear it to loop the script by nesting the setTimeout() object inside of the function it calls to run. If geared to loop, it will keep firing at the interval unless you call clearTimeout().
function doStuff() {
alert("run your code here when time interval is reached");
}
var myTimer = setTimeout(doStuff, 5000);
If you want something to happen one time after a specified period of time, then use setTimeout(). That is because it only executes one time when the specified interval is reached.
The setInterval makes it easier to cancel future execution of your code. If you use setTimeout, you must keep track of the timer id in case you wish to cancel it later on.
var timerId = null;
function myTimeoutFunction()
{
doStuff();
timerId = setTimeout(myTimeoutFunction, 1000);
}
myTimeoutFunction();
// later on...
clearTimeout(timerId);
versus
function myTimeoutFunction()
{
doStuff();
}
myTimeoutFunction();
var timerId = setInterval(myTimeoutFunction, 1000);
// later on...
clearInterval(timerId);
I find the setTimeout method easier to use if you want to cancel the timeout:
function myTimeoutFunction() {
doStuff();
if (stillrunning) {
setTimeout(myTimeoutFunction, 1000);
}
}
myTimeoutFunction();
Also, if something would go wrong in the function it will just stop repeating at the first time error, instead of repeating the error every second.
The very difference is in their purposes.
setInterval()
-> executes a function, over and over again, at specified time intervals
setTimeout()
-> executes a function, once, after waiting a specified number of milliseconds
It's as simple as that
More elaborate details here http://javascript.info/tutorial/settimeout-setinterval
When you run some function inside setInterval, which works more time than timeout-> the browser will be stuck.
- E.g., doStuff() takes 1500 sec. to be execute and you do: setInterval(doStuff, 1000);
1) Browser run doStuff() which takes 1.5 sec. to be executed;
2) After ~1 second it tries to run doStuff() again. But previous doStuff() is still executed-> so browser adds this run to the queue (to run after first is done).
3,4,..) The same adding to the queue of execution for next iterations, but doStuff() from previous are still in progress...
As the result- the browser is stuck.
To prevent this behavior, the best way is to run setTimeout inside setTimeout to emulate setInterval.
To correct timeouts between setTimeout calls, you can use self-correcting alternative to JavaScript's setInterval technique.
Your code will have different execution intevals, and in some projects, such as online games it's not acceptable. First, what should you do, to make your code work with same intevals, you should change "myTimeoutFunction" to this:
function myTimeoutFunction()
{
setTimeout(myTimeoutFunction, 1000);
doStuff();
}
myTimeoutFunction()
After this change, it will be equal to
function myTimeoutFunction()
{
doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);
But, you will still have not stable result, because JS is single-threaded. For now, if JS thread will be busy with something, it will not be able to execute your callback function, and execution will be postponed for 2-3 msec. Is you have 60 executions per second, and each time you have random 1-3 sec delay, it will be absolutely not acceptable (after one minute it will be around 7200 msec delay), and I can advice to use something like this:
function Timer(clb, timeout) {
this.clb = clb;
this.timeout = timeout;
this.stopTimeout = null;
this.precision = -1;
}
Timer.prototype.start = function() {
var me = this;
var now = new Date();
if(me.precision === -1) {
me.precision = now.getTime();
}
me.stopTimeout = setTimeout(function(){
me.start()
}, me.precision - now.getTime() + me.timeout);
me.precision += me.timeout;
me.clb();
};
Timer.prototype.stop = function() {
clearTimeout(this.stopTimeout);
this.precision = -1;
};
function myTimeoutFunction()
{
doStuff();
}
var timer = new Timer(myTimeoutFunction, 1000);
timer.start();
This code will guarantee stable execution period. Even thread will be busy, and your code will be executed after 1005 mseconds, next time it will have timeout for 995 msec, and result will be stable.
I use setTimeout.
Apparently the difference is setTimeout calls the method once, setInterval calls it repeatdly.
Here is a good article explaining the difference: Tutorial: JavaScript timers with setTimeout and setInterval
I've made simple test of setInterval(func, milisec), because I was curious what happens when function time consumption is greater than interval duration.
setInterval will generally schedule next iteration just after the start of the previous iteration, unless the function is still ongoing. If so, setInterval will wait, till the function ends. As soon as it happens, the function is immediately fired again - there is no waiting for next iteration according to schedule (as it would be under conditions without time exceeded function). There is also no situation with parallel iterations running.
I've tested this on Chrome v23. I hope it is deterministic implementation across all modern browsers.
window.setInterval(function(start) {
console.log('fired: ' + (new Date().getTime() - start));
wait();
}, 1000, new Date().getTime());
Console output:
fired: 1000 + ~2500 ajax call -.
fired: 3522 <------------------'
fired: 6032
fired: 8540
fired: 11048
The wait function is just a thread blocking helper - synchronous ajax call which takes exactly 2500 milliseconds of processing at the server side:
function wait() {
$.ajax({
url: "...",
async: false
});
}
Both setInterval and setTimeout return a timer id that you can use to cancel the execution, that is, before the timeouts are triggered. To cancel you call either clearInterval or clearTimeout like this:
var timeoutId = setTimeout(someFunction, 1000);
clearTimeout(timeoutId);
var intervalId = setInterval(someFunction, 1000),
clearInterval(intervalId);
Also, the timeouts are automatically cancelled when you leave the page or close the browser window.
To look at it a bit differently: setInterval ensures that a code is run at every given interval (i.e. 1000ms, or how much you specify) while setTimeout sets the time that it 'waits until' it runs the code. And since it takes extra milliseconds to run the code, it adds up to 1000ms and thus, setTimeout runs again at inexact times (over 1000ms).
For example, timers/countdowns are not done with setTimeout, they are done with setInterval, to ensure it does not delay and the code runs at the exact given interval.
You can validate bobince answer by yourself when you run the following javascript or check this JSFiddle
<div id="timeout"></div>
<div id="interval"></div>
var timeout = 0;
var interval = 0;
function doTimeout(){
$('#timeout').html(timeout);
timeout++;
setTimeout(doTimeout, 1);
}
function doInterval(){
$('#interval').html(interval);
interval++;
}
$(function(){
doTimeout();
doInterval();
setInterval(doInterval, 1);
});
Well, setTimeout is better in one situation, as I have just learned. I always use setInterval, which i have left to run in the background for more than half an hour. When i switched back to that tab, the slideshow (on which the code was used) was changing very rapidly, instead of every 5 seconds that it should have. It does in fact happen again as i test it more and whether it's the browser's fault or not isn't important, because with setTimeout that situation is completely impossible.
The difference is obvious in console:
Just adding onto what has already been said but the setTimeout version of the code will also reach the Maximum call stack size which will stop it from functioning. Since there is no base case for the recursive function to stop at so you can't have it run forever.
If you set the interval in setInterval too short, it may fire before the previous call to the function has been completed. I ran into this problem with a recent browser (Firefox 78). It resulted in the garbage collection not being able to free memory fast enough and built up a huge memory leak.
Using setTimeout(function, 500); gave the garbage collection enough time to clean up and keep the memory stable over time.
Serg Hospodarets mentioned the problem in his answer and I fully agree with his remarks, but he didn't include the memory leak/garbage collection-problem. I experienced some freezing, too, but the memory usage ran up to 4 GB in no time for some minuscule task, which was the real bummer for me. Thus, I think this answer is still beneficial to others in my situation. I would have put it in a comment, but lack the reputation to do so. I hope you don't mind.
The reason why Option A and Option B seem like they work the same is mostly because the places of the setInterval and the setTimeout functions.
function myTimeoutFunction()
{
doStuff();
setTimeout(myTimeoutFunction, 1000);
}
myTimeoutFunction();
This one is a recursive function, and if doStuff is very complex, setTimeout has to keep track of all calls of the setTimout plus the current doStuff, which makes it become slower and s l o w e r.
function myTimeoutFunction()
{
doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);
On the other hand, the setInterval only has to keep track of the last setInterval and the current doStuff, making it staying at a constant speed.
So which one should you use?
From the above, you should probably be able to conclude that the better one is setInterval.
The important point to consider is the performance.
The only way to run a function periodically using setTimeout is to call it recursively with the target function, and when you check it, it appears that it works asynchronously put when you see the call stack you will find it keep growing by the time. In fact, it is sensible. Since Javascript does not support multi-threading, it is impossible to finish calling the parent function before finishing the child function, therefor, the stack will keep growing as long as there is recursive calling.
Whilst, with setInterval we don't need to call the target function recursively since it has a logic that runs it periodically as a loop. So, this keeps the call stack clean.
You can watch the call stack using developer's tools in your browser and you will notice the difference.
The difference will be clear when using small interval for a long period of time.
I think SetInterval and SetTimeout are different. SetInterval executes the block according to the time set while, SetTimeout executes the block of code once.
Try these set of codes after the timeout countdown seconds:
setInterval(function(e){
alert('Ugbana Kelvin');
}, 2000);
and then try
setTimeout(function(e){
alert('Ugbana Kelvin');
}, 2000);
You can see the differences for yourself.

Categories

Resources