Friday, October 26th, 2007
Running CPU Intensive JavaScript Computations in a Web Browser
Julien Lecomte has written up the pattern where you use setTimeout() to keep yielding control back to the main thread so that it can handle browser events.
Completion Callback
// Initialize a few things here...
(function () {
// Do a little bit of work here...
if (termination condition) {
// We are done
callbackFn();
} else {
// Process next chunk
setTimeout(arguments.callee, 0);
}
})();
}
Progress Callback
// Initialize a few things here...
(function () {
// Do a little bit of work here...
if (continuation condition) {
// Inform the application of the progress
progressFn(value, total);
// Process next chunk
setTimeout(arguments.callee, 0);
}
})();
}
Of course, the Gears Workerpool does this the right way, giving you the ability to pass messages to another process to get the work done in a secure sandbox.
As a band-aid it could be nice to have an abstraction library that uses WorkerPool if Gears is installed, if not, try to use setTimeout (which is harder to do as you need to cut up the work differently).







This method is being used for over ten years now. Have a look at something way more advanced: continutations.
http://marijn.haverbeke.nl/cps/
@Robbert,
This isn’t a new pattern, of course. My goal in this article was to present this well known pattern under a new light, and discuss ways of reducing the overhead associated with it without sacrificing user interface reactivity.
Regards
…now why didn’t I think of that? I’m always locking my browser down with JavaScript — I usually just depend on nice, muted, pastel-coloured “waiting” screen to pacify users…
This and the continuation approach are neat ideas, but I would also argue that if your code is encountering very heavy blocks (number crunching, large DOM node creation or ?) often, your approach could probably be refactored a little bit or perhaps moved to the backend if appropriate. I say this only because of JS’ current non-threaded, blocking-type behaviour (“this is what we have to work with”, etc.)
@Scott
I totally agree with you, and point this out in the last paragraph of the original article.
Well, the browser *can* handle CPU intensive computations to some extent (see the examples linked in the original article) and hopefully, with the next generation JavaScript engines (Tamarin), this will be even more true. The real question is whether doing that computation on the client is the *best* approach, and this depends on your situation.
An old technique to solve a still current problem, so it is good to revisit it, especially where resources are a consideration. This is making me think about mobile browsing applications: A JS computation can be CPU intensive because it’s running on a 400MHz ARM rather than a 3Ghz P4 — heavy code blocks are relative to the platform.
I am inspired to do some mobile browser tests, as it’s often very hard to determine if a device is hanging or I’m not pressing the screen right!
@Julien – Good point, the examples definitely show a way to overcome that hurdle.
This trouble is focused in the GWT’s IncrementalCommand interface. I’m developing a text compressor with this pseudo concurrent approach.