Web workers example with queue
by PhilQ
HTML
<script id="worker1" type="javascript/worker">
self.onmessage = function(e) {
self.postMessage({
status: 'running',
message: 'Running task ' + e.data.id + '...'
});
setTimeout(function(){
self.postMessage({
status: 'done',
message: 'Finished task ' + e.data.id
});
}, 1000 + Math.random()*2000);
};
</script>
JavaScript
// Create worker code (instead of external file)
var blob = new Blob([
document.querySelector('#worker1').textContent
], {
type: "text/javascript"
});
// Note: window.webkitURL.createObjectURL() in Chrome 10+.
var workerObjectUrl = window.URL.createObjectURL(blob);
// Web worker set-up
var numberOfCores = 4; // See: https://github.com/oftn-oswg/core-estimator
var workers = new Array(numberOfCores).fill(null);
var tasks = [];
var tasksRemaining = 0;
var tasksCompletedCallback = () => {};
// Define web worker handling
function handleWorker(worker, e, workerIdx) {
let txtColor = (e.data.status === 'running') ? 'color:orange;': 'color:green;';
console.log('W' + workerIdx + ': %c' + e.data.message, txtColor);
if (e.data.status === 'done') {
tasksRemaining--;
if (tasks.length > 0) {
worker.postMessage(tasks.shift());
} else if (tasksRemaining === 0) {
tasksCompletedCallback();
}
}
}
// Initiate web workers
workers.map((v, i, a) => {
workers[i] = new Worker(workerObjectUrl);
workers[i].onmessage = function(e) {
handleWorker(this, e, i);
}
});
// Function to control, queue and starting tasks
function runTasks(_tasks, _callback) {
if (tasksRemaining > 0 || tasks.length > 0) {
console.error('Previous tasks did not finish yet');
return;
}
tasks = _tasks;
tasksRemaining = tasks.length;
tasksCompletedCallback = _callback;
let max = Math.min(tasks.length, workers.length);
for (let i = 0; i < max; i++) {
workers[i].postMessage(tasks.shift());
}
}
// Start running tasks
runTasks(
[
{id:1},
{id:2},
{id:3},
{id:4},
{id:5},
{id:6},
{id:7},
{id:8},
{id:9},
{id:10}
], () => {
console.log('--- DONE ---');
// Run next set of tasks
runTasks(
[
{id:'A'},
{id:'B'},
{id:'C'},
{id:'D'},
{id:'E'},
{id:'F'}
], () => {
console.log('--- DONE ---');
}
);
}
);