Skip to content

Instantly share code, notes, and snippets.

@airbreather
Created August 10, 2024 17:45
Show Gist options
  • Save airbreather/3f3587e82fa96903b22cf66a6b3ab5dd to your computer and use it in GitHub Desktop.
Save airbreather/3f3587e82fa96903b22cf66a6b3ab5dd to your computer and use it in GitHub Desktop.
Promisify a Web Worker?
type Serializable =
| void
| undefined
| null
| number
| bigint
| string
| boolean
| ReadonlyArray<Serializable>
| Readonly<{ [key: string]: Serializable }>
| ReadonlyMap<Serializable, Serializable>
| ReadonlySet<Serializable>
| Date
| RegExp
| Blob
| File
| ImageData
| ArrayBuffer
| SharedArrayBuffer;
const runInWorker = <Input extends Serializable, Output extends Serializable>(f: (i: Input) => Output | Promise<Output>, i?: Input) => {
return new Promise<Output>((resolve, reject) => {
const workerFn = () => self.onmessage = async (evt: MessageEvent<[string, Input]>) => postMessage(await Promise.resolve(eval(evt.data[0])(evt.data[1])));
const workerCode = new Blob([`(${workerFn})()`], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(workerCode));
worker.onmessage = (ev: MessageEvent<Output>) => resolve(ev.data);
worker.onerror = reject;
worker.postMessage([`${f}`, i]);
});
};
console.log('worker says (should be 32)', await runInWorker(() => 32));
console.log('worker says (should be 8n)', await runInWorker(i => i * 2n, 4n));
console.log('worker says (should be 11)', await runInWorker(async i => new Promise<number>(resolve => resolve(i + 3)), 8));
@airbreather
Copy link
Author

airbreather commented Aug 10, 2024

This is kinda crappy since you can't use any imports, but I imagine it's got to be nice to be able to write code with full TypeScript type checking and syntax highlighting right alongside the other code that calls it. I'm surprised not to find something more-or-less equivalent to this out there.

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