JavaScript's setTimeout()
and setInterval()
are evil and not precise:
Both functions have a delay of a varying quantity of milliseconds.
Both functions are very resource-intensive because they execute several times every second.
A new alternative is window.requestAnimationFrame()
, which is less resource-intensive, disabled on page blur, and does not slow down other stuff. This makes it the perfect substitute for a modern setTimeout()
and setInterval()
.
Description
These functions use requestAnimationframe()
to check if the time has passed
based on the elapsed Time calculated from Date.now()
. The time passed is more precise than the native functions and theoretically less resource-intensive. Another advantage (or disadvantage) is that the functions are not executed on page blur.
Good for: animations, visual effects
Bad for: timers, clock
RafTimeout
window.rtimeOut=function(callback,delay){
var dateNow=Date.now,
requestAnimation=window.requestAnimationFrame,
start=dateNow(),
stop,
timeoutFunc=function(){
dateNow()-start<delay?stop||requestAnimation(timeoutFunc):callback()
};
requestAnimation(timeoutFunc);
return{
clear:function(){stop=1}
}
}
RafInterval
window.rInterval=function(callback,delay){
var dateNow=Date.now,
requestAnimation=window.requestAnimationFrame,
start=dateNow(),
stop,
intervalFunc=function(){
dateNow()-start<delay||(start+=delay,callback());
stop||requestAnimation(intervalFunc)
}
requestAnimation(intervalFunc);
return{
clear:function(){stop=1}
}
}
Usage
var interval1,timeout1;
window.onload=function(){
interval1=window.rInterval(function(){console.log('interval1')},2000);
timeout1=window.rtimeOut(function(){console.log('timeout1')},5000);
}
/* to clear
interval1.clear();
timeout1.clear();
*/
Demo
Questions
Normally I don't write functions inside functions, but in this case it's probably a good solution. What about memory leaks if I create hundreds of these time-based functions?
Is there a better solution to clear those functions?
For heavy animations and multiple intervals and timeouts, I was thinking to activate a single
requestAnimationFrame()
loop which would check for intervals and timeouts inside a previously stored array... (but I think there should be no difference if there is just onerequestAnimationframe
or multiple). So how do the browsers handle those multiplerequestAnimationframes()
?
Note:
If the code above does not work here is the original code:
window.rInterval=function(a,b){var c=Date.now,d=window.requestAnimationFrame,e=c(),f,g=function(){c()-e<b||(e+=b,a());f||d(g)};d(g);return{clear:function(){f=1}}}//callback,delay
window.rtimeOut=function(a,b){var c=Date.now,d=window.requestAnimationFrame,e=c(),f,g=function(){c()-e<b?f||d(g):a()};d(g);return{clear:function(){f=1}}}
requestAnimationFrame
is called on average 60 times per second.. At first sight, your code is far eviler. \$\endgroup\$setTimeout
checks more often, that is the first I hear of that \$\endgroup\$requestAnimation
10 times, it would have executedsetTimeout
once, right ? \$\endgroup\$