Wrapping Functions In Web Workers
How to wrap arbitrary functions, that may take a while, in a web worker thread.
HTML
<button>Do It</button>
CSS
body {
margin: 1.8em;
}
p {
font: 0.8em "courier new";
}
JavaScript
/*
* Wraps "func" with a web worker thread, and
* returns a jQuery deferred so the caller can
* get the result.
*
*/
function worker( func ) {
return (function() {
// Creates the blob URL. We have to construct
// the web worker code here by-hand.
var blob = URL.createObjectURL( new Blob( [ "\
onmessage = function(){\
postMessage((" + func.toString() + ")());\
};"])),
// The web worker the actually runs the code,
// and the deferred used to pass the result
// back to the caller.
worker = new Worker( blob ),
deferred = new $.Deferred();
// We can resolve the deferred when we hear back
// from the web worker thread.
worker.onmessage = function( e ) {
deferred.resolve( e.data );
};
// Start the worker, and return the deferred back
// to the caller.
worker.postMessage('');
return deferred;
});
}
// Arbitrary worker function that takes
// some time to complete. Returns the time
// it took to do the computations.
function doWork() {
var start = new Date(), stop;
for ( var i=0; i<100000; i++ ) {
for ( var j=0; j<100000; j++ ) {
j * 1000000;
}
}
stop = new Date();
return stop - start;
}
// Use the "worker" wrapper to make "doWork",
// an asynchronous web worker thread that returns
// a deferred.
var asyncWork = worker( doWork );
$(function() {
$( 'button' ).click(function( e ) {
// For illustrative purposes, disable the button.
$( this ).prop( 'disabled', true );
// Do some work that'll take at least a few seconds
// to complete.
asyncWork().done(function( result ) {
$( '<p/>' ).text( result / 1000 )
.appendTo( 'body' );
});
// For illustative purposes, re-enable the button.
...