Difference between revisions of "Useful functions"
From SoundDB
(Created page with "<pre> setTimeout with a shorter delay Wednesday, 2010-03-09, 13:45 -0800 On Sunday, somebody with the nickname {g} was on irc.mozilla.org asking about the behavior of setTimeou...") |
|||
Line 42: | Line 42: | ||
Update (2010-03-12): My numbers were on Linux. Boris tells me that on Mac, it's the opposite: Gecko is faster than Safari or Chrome. | Update (2010-03-12): My numbers were on Linux. Boris tells me that on Mac, it's the opposite: Gecko is faster than Safari or Chrome. | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | <pre> | ||
+ | function doCalculation() | ||
+ | { | ||
+ | //do your thing for a short time | ||
+ | //figure out how complete you are | ||
+ | var percent_complete=.... | ||
+ | return percent_complete; | ||
+ | } | ||
+ | function pump() | ||
+ | { | ||
+ | var percent_complete=doCalculation(); | ||
+ | //maybe update a progress meter here! | ||
+ | //carry on pumping? | ||
+ | if (percent_complete<100) | ||
+ | { | ||
+ | setTimeout(pump, 50); | ||
+ | } | ||
+ | } | ||
+ | //start the calculation | ||
+ | pump(); | ||
</pre> | </pre> |
Revision as of 12:47, 25 May 2011
setTimeout with a shorter delay Wednesday, 2010-03-09, 13:45 -0800 On Sunday, somebody with the nickname {g} was on irc.mozilla.org asking about the behavior of setTimeout. In particular, he wanted to divide up work into a bunch of pieces in a way that allowed the user to interact with the page while the work was happening, and was doing this by doing a piece of the work, and then making a setTimeout call to continue the work. (In some cases, this could also be done using workers.) Unfortunately for him, setTimeout in most browsers doesn't allow a delay less than about 10 milliseconds (it forces any smaller delays to be longer), so the work wasn't finishing as fast as it could. (Chrome has changed this to 2 milliseconds, though, and apparently had some problems with it.) A while ago, Jeff Walden suggested to me that Web pages could get the equivalent of setTimeout, with a real zero delay, using postMessage. This turns out to be relatively straightforward: // Only add setZeroTimeout to the window object, and hide everything // else in a closure. (function() { var timeouts = []; var messageName = "zero-timeout-message"; // Like setTimeout, but only takes a function argument. There's // no time argument (always zero) and no arguments (you have to // use a closure). 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); // Add the one thing we want added to the window object. window.setZeroTimeout = setZeroTimeout; })(); I wrote a demo page that demonstrates that this is significantly faster than setTimeout(0). On a Firefox nightly 100 iterations of setZeroTimeout take about 10-20 milliseconds most of the time, but occasionally longer; on a WebKit build I have it takes about 4-6 milliseconds, but occasionally a bit longer. (We should probably investigate the performance difference here.) In comparison, in Firefox and on non-Chromium-based WebKit, the setTimeout version takes about a second (though perhaps even longer on Windows). Update (2010-03-12): My numbers were on Linux. Boris tells me that on Mac, it's the opposite: Gecko is faster than Safari or Chrome.
function doCalculation() { //do your thing for a short time //figure out how complete you are var percent_complete=.... return percent_complete; } function pump() { var percent_complete=doCalculation(); //maybe update a progress meter here! //carry on pumping? if (percent_complete<100) { setTimeout(pump, 50); } } //start the calculation pump();