Skip to content

Instantly share code, notes, and snippets.

@dtipson
Last active March 15, 2020 15:39
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dtipson/d11f8068ae3a5f1907228fc2888b3705 to your computer and use it in GitHub Desktop.
Save dtipson/d11f8068ae3a5f1907228fc2888b3705 to your computer and use it in GitHub Desktop.
Template literals allow us to write string code suitable for workers. We can even import actual functions using toString. Blob urls allow us to turn all that content into a script for the worker to run, allowing us to create and run one with no external dependencies!
//actual function (must be a named function declaration for use w/ toString here)
function addOne(x){ return x+1 };
//the actual worker code can be written as a string
//template literals make that convienient because they support multiline
//note that the addOne function above can be used in this worker code, since we'll be importing it
const workerScript = `
self.addEventListener('message', function(e) {
var data = e.data;
console.log('worker recieved: ',data);
self.postMessage('worker added! :'+ addOne(data.value));
}, false);
`;
//main function for creating an inline worker:
//inlineWorker:: Array -> String -> a -> Promise b
const inlineWorker = (dependencies=[], scriptString, msg) => {
scriptString = dependencies.reduce((acc,item) => acc+item.toString(),'') + scriptString;
//promisify the response/error for make things easier to consume
const promise = new Promise( (resolve, reject) => {
var blob = new Blob([scriptString], { type: "text/javascript" });
var bloblurl = window.URL.createObjectURL(blob);
var worker = new Worker(bloblurl);
worker.onmessage = e => {
resolve(e.data);
window.URL.revokeObjectURL(bloblurl);//remember to free up the blob url as well
worker.terminate();
};
worker.onerror = e => {
reject(e);
worker.terminate();
};
worker.postMessage(msg);
});
return promise;
}
inlineWorker([addOne],workerScript,{msg:'hi', value:6}).then(x=>console.log('msg returned: ',x));
@dtipson
Copy link
Author

dtipson commented May 6, 2016

The main problem with this approach is just that linters aren't going to pick up on any errors in the template literal string (because it's just a string). So you'd either want to write/test that code before adding const stringName=``; around it, or try to define an arrow function expression with the worker code inside it and then run .toString on that (because the expression version will sort of "remove" the outer wrapping when toStrung).

There are potentially more powerful techniques possible using serviceWorkers and sharedWorkers: http://stackoverflow.com/a/19201292/1971194

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment