Skip to content

Instantly share code, notes, and snippets.

@therightstuff
Created May 11, 2018 12:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save therightstuff/eb415798b0e30866fe85d66af68969cf to your computer and use it in GitHub Desktop.
Save therightstuff/eb415798b0e30866fe85d66af68969cf to your computer and use it in GitHub Desktop.
Web Worker callback design pattern
// ensure window object available
var window = self;
self.addEventListener('message', function (e) {
var payload = e.data;
var result = null;
var err = null;
switch (payload.cmd) {
case 'sampleCommand':
console.log("worker processing sampleCommand");
result = 'example result ' + payload.data.echo;
break;
default:
console.log("worker not processing unknown command");
err = 'Unknown command ' + payload.cmd;
};
// return result to main thread
self.postMessage({ callId: payload.callId, result: result, error: err });
}, false);
var workers = {};
workers.nextCallId = 0;
workers.callbacks = {};
// handle worker responses
workers.handler = function (e) {
if (!workers.callbacks[e.data.callId]) {
console.info('worker ' + e.data.callId + ' callback not defined on ' + (e.data.error ? 'error' : 'success'));
} else {
if (e.data.error) {
// log error
console.error('worker ' + e.data.callId + ' callback on error');
console.error('worker ' + e.data.callId + ' error: ' + e.data.error);
workers.callbacks[e.data.callId](e.data.error);
} else {
// send data to callback function
console.info('worker ' + e.data.callId + ' callback on success');
workers.callbacks[e.data.callId](null, e.data.result);
}
// remove callback reference
workers.callbacks[e.data.callId] = null;
}
};
myExampleWorker = new Worker('exampleWorker.js');
myExampleWorker.addEventListener('message', workers.handler, false);
// wrapper for postMessage
workers.post = function (worker, cmd, data, cb) {
var callId = workers.nextCallId++;
// register callback function
workers.callbacks[callId] = cb;
// post data to worker
worker.postMessage({cmd:cmd, callId: callId, data:data});
};
<html>
<head>
<script src="manager.js"></script>
<script lang="javascript">
function logResult(command, result){
document.getElementById("logs").value += command + ": " + result + '\n';
}
function logError(command, error){
document.getElementById("logs").value += command + " ERROR: " + error + '\n';
}
function test1() {
// works, result is "example result works"
workers.post(myExampleWorker, 'sampleCommand', { echo: 'works' }, function (err, result) {
if (err){
logError('sampleCommand', err);
} else {
logResult('sampleCommand', result);
}
});
}
function test2() {
// works with no callback
workers.post(myExampleWorker, 'sampleCommand', { echo: 'works with no callback' });
}
function test3() {
// fails with no callback
workers.post(myExampleWorker, 'invalidCommand', { echo: 'fails with no callback' });
}
function test4() {
// fails with bad command
workers.post(myExampleWorker, 'invalidCommand', null, function (err, result) {
if (err){
logError('invalidCommand', err);
} else {
logResult('invalidCommand', result);
}
});
}
</script>
</head>
<body>
<button onclick="test1()">Success</button>
<button onclick="test2()">Success with no callback</button>
<button onclick="test3()">Failure with no callback</button>
<button onclick="test4()">Failure with callback</button>
<hr />
<textarea id="logs" rows="10" cols="80"></textarea>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment