In javascript, setTimeout is forced to be >= 4 msec
source link: https://blog.klipse.tech/javascript/2016/10/31/setTimeout-0msec.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
In javascript, setTimeout is forced to be >= 4 msec
Oct 31, 2016 • Yehonathan Sharvit
Javascript is a language full of surprises: there are the good parts
and the bad parts
. Today, I discovered that setTimeout
featured a minimal delay of 4 msec.
This is well documented in Reasons for delays longer than specified.
But I wonder, how many experienced javascript developers are aware of this weird behaviour.
What about you?
Did you know that the minimal delay of setTimeout
was 4 msec?
In this article, we are going to:
- demonstrate the 4 sec delay added by the browser when one uses a
setTimeout
with 0 delay. - demonstrate how to write 0-delay timers using
postMessage
.
Code example
All the code snippets of this page are live and interactive powered by the klipse plugin:
- Live: The code is executed in your browser
- Interactive: You can modify the code and it is evaluated after 3 seconds of inactivity of if you press
Ctrl-Enter
inside the code snippet.
The 4 msec delay in action
Here is the code that demonstrates the 4-msec delay - calling setTimeout
recursively 100 times with a 0
delay.
As you can see by yourslef, the execution time for 100 iterations is around 400 msec.
You might need to reevaluate the snippet - for some reason the first evaluation takes much more time.
Press Ctrl-Enter
inside the code snippet or modify the code and wait for 3 seconds…
xxxxxxxxxx
function bar(iterations) {
if(iterations === 0) {
console.log("done in: " + (new Date() - startTimeout)+ " msec")
}
else {
setTimeout(bar, 0, iterations - 1);
}
}
startTimeout = new Date();
console.log("Start");
bar(100);
"Start"
Amazing. No?
The solution for fast timeouts
If we want to have a 0 msec
timer, we have to use postMessage
.
So, let’s do it and take the following code from setTimeout with a shorter delay.
setZeroTimeout
takes a single argument: the callback function that is going to be called with 0 delay - but asynchronously.
xxxxxxxxxx
(function() {
var timeouts = [];
var messageName = "zero-timeout-message";
function setZeroTimeout(fn) {
timeouts.push(fn);
window.postMessage(messageName, "*");
}
function handleMessage(event) {
if (event.source == window && event.data == messageName) {
event.stopPropagation();
if (timeouts.length > 0) {
var fn = timeouts.shift();
fn();
}
}
}
window.addEventListener("message", handleMessage, true);
window.setZeroTimeout = setZeroTimeout;
})();
xxxxxxxxxx
undefined
And now, let’s see it in action - in my browser, it takes around 17 msec for 100 iterations.
Again, you might need to reevaluate the snippet - as the first evaluation takes much more time.
Press Ctrl-Enter
inside the code snippet or modify the code and wait for 3 seconds…
xxxxxxxxxx
function runBaz(iterations) {
function baz() {
if(--iterations === 0) {
console.log("done in: " + (new Date() - startZeroTimeout) + " msec")
}
else {
setZeroTimeout(baz);
}
}
baz();
}
startZeroTimeout = new Date();
console.log("OK");
runBaz(100);
xxxxxxxxxx
"OK"
"done in: 276 msec"
By the way, what do you think about the interactive code snippets powered by KLIPSE?
You might what to give a star on Github…
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK