After some time of hearing about the awesome new HTML5 Web Workers but having no particular need for them, I was finally presented with a problem that they could help me with. I promptly sat down with a handful of Google search results and went a-learnin. Turns out they're basically pretty simple. ( except for a small syntactic gotcha in Chrome, more about that later )
There is one major flaw with them though. As far as I could tell, there's no good way to write your javascript code once, in one form, and have it gracefully degrade to non-Worker enabled browsers (If someone knows differently, please let me know in the comments).
So, the gist of the Workers setup is that your main javascript code will "kick off" a "thread" in the background, telling that thread a separate javascript file to download and execute. This seemed to me to be the first interesting compatibility breaker. What was once written in one file, would now be separated into two files. Secondly the two "threads" communicate through messages, something that doesn't much exist pre-HTML5.
For my needs, the code in the "Worker" should still execute and function if Workers are not available in a user's browser. Sure the user will have a performance impact, but the page should still function. All that I could find around the web were statements like:
if( Worker ) { // algorithm with workers} else { // algorithm without workers}That would cause me to duplicate considerable amounts of my codebase, and be a case-by-case solution. Anytime those come up, there must be a better solution!
I quickly modified what I was working on to function via the native Worker implementation in Chrome and Firefox, but then my attention immediately turned to creating a wrapper that would behave like a native Worker (albiet far less efficient) in browsers which had no native implementation.
Turns out, it wasn't all that difficult - due to the simplistic nature of the interface between the two threads. I've bundled it up as a jQuery extension here (sadly the extensions site is down due to spamming).
(function($){
$.worker = function(path) {
if('undefined' === typeof(Worker)){
function IWorker() {
var __w = this;
var messageq = [];
__w.postMessage = function(m){messageq.push(m);};
this.__bindBody = function(data){
var __win = { postMessage : function(m){
if(__w.onmessage){
setTimeout(function(){ __w.onmessage({data: m});}, 1);
}
}
};
with(__win){
eval(data);
__w.postMessage = (onmessage)
? function(m) { setTimeout(function() {onmessage({data: m});}, 1); }
: function(){};
for(var i=0,msg;msg=messageq[i];i++){
__w.postMessage(msg);
}
}
}
}
var iworker = new IWorker();
$.get(path, function(data) {
iworker.__bindBody(data);
});
return iworker;
} else {
return new Worker(path);
}
}
})(jQuery);
To use it, simply replace new Worker("myfile.js") with $.worker("myfile.js"). If the browser supports Workers natively, it'll just fallthrough and use it. Otherwise, it will grab the worker file via ajax, wrap it in a scope that simulates a worker and provides the needed postMessage and onmessage API hooks.
// pre-pluginvar w = new Worker("myfile.js");w.onmessage = function(e) { alert(e.data); }w.postMessage("Hi");// post-pluginvar w = $.worker("myfile.js");w.onmessage = function(e) { alert(e.data); }w.postMessage("Hi");
One glaring omission that I have yet to need, is that this implementation does not mimc the onerror event that is possible with Workers. I plan to implement this, but likely won't until either I need it, or someone else asks me to :)
Oh, and the "syntactic gotcha in Chrome" that I mentoined before, kept me spinning for a good hour or more....
In your worker.js file, in order to capture incoming messages, you define a method:
onmessage = function(e){
// do something with e.data
};That seems straight-forward, though, it is interestingly NOT equivalent to
function onmessage(e){
// do something with e.data
}in Chrome (though it works fine in Firefox). So, be sure to use the first syntax.
After posting this, of course I came across another implementation out on the interwebs. http://code.google.com/p/ie-web-worker/source/browse/trunk/worker.js
ReplyDeleteIt is very nice work to get money on your hand in house. We can get money to do work online in our house. These work depends on internet and money company search free lancer employee for their work.
ReplyDeleteVisit: Webworker
It’s refreshing to read a good quality article for a change. You’ve made many interesting points and I agree. This has made me think and for that I thank you.
ReplyDeleteVisit: Webworker