setTimeout
, setInterval
, and requestAnimationFrame
are 3 most common APIs for scheduling call.
setTimeout
: allows us to run function once after given time.
setInterval
: allows us to run function repeatedly starting after given time, repeating continuously at the interval.
setTimeout(callback, delay, arg1, arg2,...)
Parameter from arg1, arg2,.. is optional.
Call to setTimeout returns "timer identifier" timerId
.
We can use clearTimeout
to cancel execution. The callback given as a parameter stays in memory untill we call clearTimeout
.
Most parts of syntax is similar to setTimeout
. Instead of clearTimeout
, we use clearInterval
.
let timerId = setInterval(()=>alert('tick'), 2000);
setTimeout(()=>{clearInterval(timerId); alert('stop');}, 5000);
In above snippet, we planned to print 'tick' for every 2sec, and it stops after 5sec.
For scheduling repeated function, there is a alternative for setInterval
. It is using nested setTimeout. The advantage is that we can set delay between executions more precisely. It's more flexible.
let delay = 2000;
let timerId = setTimeout(function tick() {
delay = 2000;
console.log('tick');
timerId = setTimeout(tick, 2000); // (*)
const random = Math.random(0,1000);
console.log(random)
if(random%2 == 0) {
delay = 1000;
}
}, delay);
Note that both of methods do not guarantee exact delay of given time.
setInterval
calls function in given interval. It only guarantees that function will be passed to STACK in exeact interval. For example, if the given interval is 1sec, it means that function is called every 1sec.
One big disadvantage of this mechanism is that It doesn't guarantees the interval of execution. If the previous function ofsetInterval
's execution takes lots of time, the callback of setInterval
can be executed unexepectedly.
On the other hand, Nested setTimeout guarantees untill our method gets fully executed it will never be sent for another execution.
Another alternative for handling repeating callback is using aync setInterval
.
const setIntervalAsync = (fn, ms) => {
fn().then(() => {
setTimeout(() => setIntervalAsync(fn, ms), ms);
});
};
setIntervalAsync(() => fetch(/* blah */), 3000);
If we set interval of setTimeout
to 0, it is not executed right away. The reason is because setTimeout
is handled by Web API and task queue and then pushed to stack. So, it is scheduled 'right after' the current script. If current script is over, which means that stack is empty, then it is executed.
requestAnimationFram
is used when we have to handle repeated animation changes in javascript.
As mentioned above, the interval between animation is inconsistent.
Layout thrashing happens. Layout thrashing is when browser is froced to perform unnecessary reflows of the page before the user's screen is able to display the changes.
It allows me to execute code on the enxt available screen repaint, which syncs with browser & hardware. It makes smoother animation.
If the page is in inactive tabls, animation stops automatically, whcih saves system resources.
Battery-friendly.
requestAnimationFrame(callback)
Runs callback when screen is ready to accept the next screen repaint.
The callback function automatically passes timestamp
which indicates the precise time requestAnimationFrame
is called.
requestAnimationFrame
returns non 0 integer that can be passed to cancelAnimationFrame
for cancelling it.
To repeatedly call callback function, we should use it recursively.
function repeat(){
// animation
requestAnimationFrame(repeat);
}
requestAnimationFrame(repeat);