A worker runs some code in a separate process.
No DOM or window access, limited API.
Communicates via postMessage API.
Pretty good sandbox
Ideal for discrete tasks
Longer running, CPU intensive
Frees up the render thread
index.js:
var worker = new Worker('/worker.js');
worker.onmessage = function(message){
console.log('Message from worker: ' + message.data);
};
worker.postMessage('Hello Worker!');
worker.js:
addEventListener('message', function(e) {
// Print the message
console.log('Message from page: ' + e.data);
// Send a greeting in reply.
if(e.data.match(/Hello/)){
postMessage('Hello back.');
}
}, false);
myWorker.postMessage([mixed] aMessage, [array] transferList);
Modern browsers support Structured Clone.
Duplicates your message
to send to the worker.
Transfer ArrayBuffers via transferList
.
index.html
var echoWorker = new Worker('/scripts/echoworker.js');
echoWorker.onmessage = function(message){
console.log('%cMessage from worker: ', 'color: darkred', message);
};
echoworker.js
addEventListener('message', function(e) {
console.log('%cMessage from parent: ', 'color: blue', e.data);
postMessage(e.data);
}, false);
var selectedFile = document.getElementById('input').files[0];
var reader = new FileReader();
reader.onload = function(e){
window.arrayBuffer = e.target.result;
console.log('Loaded file, byteLength: ', arrayBuffer.byteLength);
console.groupEnd();
};
reader.readAsArrayBuffer(selectedFile);
Most of the non-DOM APIs are available.
window
Lots of browser code expects the global to be window
// Map `window` to `self` inside a closure (function(window){
if(window.indexedDB){ doStuff(); }
})(self);
window
// nuclear option
self.window = self;
Low-end Firefox OS benchmark (via Mozilla Hacks):
Operation | Cost |
---|---|
Initialisation | ~40ms |
postMessage latency | ~0.5ms |
Communication speed | 45kB/ms |
Opinion: Use fewer, generalist workers.
Limit to CPU cores -1.
navigator.hardwareConcurrency (and polyfills)
Workers aren't smart, but you can make smart things.
workerproxy gives you some sugar:
var proxyWorker = createWorkerProxy(new Worker('proxyworker.js'));
createWorkerProxy({
greet: function(name, callback) {
callback(null, 'Hello, ' + name + '!');
},
tokenize: tokenize,
pluralize: pluralize
}, {autoCallback: true});
npm install browserify workerify
browserify -t workerify index.js
var worker = new Worker(window.URL.createObjectURL(
new Blob(['BROWSERIFIED CONTENTS OF worker.js'])
));
Only useful for dedicated worker.
Inlined files can be difficult to debug.
Can't (easily) uglify the worker code.
Lose out on compiler optimisations.
Workers are not something you notice.