Skip to content

Instantly share code, notes, and snippets.

@morten-olsen
Created October 9, 2017 10:52
Show Gist options
  • Select an option

  • Save morten-olsen/81706544c40a993b67c2941a15728ea0 to your computer and use it in GitHub Desktop.

Select an option

Save morten-olsen/81706544c40a993b67c2941a15728ea0 to your computer and use it in GitHub Desktop.
A web worker wrapper for loading scripts from strings, and executing functions as promises
(async () => {
const worker = new WorkerScript();
await worker.loadScript(`
return new Promise((resolve) => {
setTimeout(() => {
resolve('Sample output for ' + inputs.hello);
}, 500)
})
`);
const output = await worker.run({ hello: 'world'});
console.log('output', output);
});
class WorkerScript {
constructor() {
this.requestId = 0;
const wrapper = `
let fn = undefined;
self.addEventListener('message', async ({ data }) => {
const { type, payload, id } = data;
const response = {
id,
payload: undefined,
error: false,
};
try {
switch (type) {
case 'load-script': {
fn = new Function('inputs', payload);
break;
}
case 'run': {
response.payload = await fn(payload);
break;
}
}
} catch (ex) {
response.error = true;
response.payload = ex.toString();
}
self.postMessage(response);
});
`;
const blob = new Blob([wrapper], {type: 'application/javascript'});
this.worker = new Worker(URL.createObjectURL(blob));
}
async evaluate(type, payload) {
return await new Promise((resolve, reject) => {
const currentId = this.requestId++
const handler = ({ data }) => {
const { id, payload, error } = data;
if (id === currentId) {
if (error) {
reject(error);
} else {
resolve(payload);
}
this.worker.removeEventListener('message', handler);
}
};
this.worker.addEventListener('message', handler);
this.worker.postMessage({
type,
payload,
id: currentId,
});
})
}
async loadScript(script) {
return await this.evaluate('load-script', script);
}
async run(data) {
return await this.evaluate('run', data);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment