Web workers are great; they provide a powerful way to run background threads on website.
I wanted to create a more convenient way to deal with them in a jQuery-esque way. This code allows you to create a web worker and returns a jQuery.Deferred
extended with some of the web worker methods on the instance.
// Alias vendor prefixes to standard.
if (!window.BlobBuilder) {
window.BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder;
}
if (!window.URL) {
window.URL = window.webkitURL || window.mozURL;
}
$.worker = function(args) {
var def = $.Deferred(function(dfd) {
var worker;
if (window.Worker) {
var url = args.file;
// If we have found a DOM object related,
// we need constructo a `BlobBuilder` to
// inline the web worker.
if(args.id){
var dom = document.querySelector('#' + args.id),
blob = new BlobBuilder();
blob.append(dom.textContent);
url = window.URL.createObjectURL(blob.getBlob());
}
// Construct the Web Worker
var worker = new Worker(url);
// If the Worker reports success, resolve the Deferred
worker.onmessage = function(event) {
dfd.resolve(event);
};
// If the Worker reports an error, reject the Deferred
worker.onerror = function(event) {
dfd.reject(event);
};
// Create a pointer to 'postMessage' on the Deferred
this.postMessage = function(msg){
worker.postMessage(msg);
};
this.terminate = function(){
worker.terminate();
};
// If args were passed, start the worker with supplied args
if(args.args){
worker.postMessage(args.args);
}
}
});
return def;
};
Now we call it like:
var worker = $.worker({
file: 'test_worker.js',
args: { anArg: "hello!" }
}).then(function(data) {
// Worker completed successfully
}).fail(function(data){
// Worker threw an error
});
Since we attached the postMessage
to the instance of the Deferred we return we can call postMessage
like:
worker.postMessage("monkey");
we can use jQuery.when
like:
var work1 = $.worker(doStuff, {a:1, b:50});
var work2 = $.worker(doStuff, {a:51, b:100});
$.when(work1, work2).then(function(result1, result2){
//success - do something with result1 and result2
}).fail(function(event){
//exception occurred! look at the event argument.
});
Inline workers are also supported by this, like so:
<script id="worker" type="app/worker">
// Web worker code here
</script>
$.worker({
id: 'worker',
args: { anArg: "hello!" }
});