Skip to content

Instantly share code, notes, and snippets.

@gitawego
Last active January 23, 2025 08:19
Show Gist options
  • Save gitawego/eba2712acd347b30c5865e293a4bce6d to your computer and use it in GitHub Desktop.
Save gitawego/eba2712acd347b30c5865e293a4bce6d to your computer and use it in GitHub Desktop.
webworker
/**
* example of worker (ex: worker.ts)
*
* ```ts
* self.addEventListener('message', (event) => {
const { eventName, data, messageId } = event.data;
switch (eventName) {
case 'double':
const result = data * 2;
self.postMessage({ eventName,messageId, result });
break;
case 'square':
const squared = data * data;
self.postMessage({ eventName,messageId, result: squared });
break;
default:
self.postMessage({ eventName,messageId, error: 'Unknown event name' });
}
});
`*``
*/
export class WebWorker<D extends object> {
constructor(readonly worker: Worker) {}
uuid(): string {
try {
return crypto.randomUUID();
} catch (err) {
return `${Date.now()}`;
}
}
sendMessageToWorker<R = any, K extends keyof D = keyof D>(
eventName: K,
data?: D[K],
timeout = 5e3
): Promise<R> {
return new Promise((resolve, reject) => {
const messageId = `${eventName as string}-${this.uuid()}`;
let timer: NodeJS.Timeout;
const handleMessage = (event: MessageEvent) => {
if (
event.data.eventName === eventName &&
event.data.messageId === messageId
) {
clearTimeout(timer);
this.worker.removeEventListener('message', handleMessage);
if (event.data.error) {
reject(new Error(event.data.error));
} else {
resolve(event.data.result);
}
}
};
this.worker.addEventListener('message', handleMessage);
if (timeout && timeout > 0) {
timer = setTimeout(() => {
this.worker.removeEventListener('message', handleMessage);
reject(
new Error(
`Timeout: No response for event "${eventName as string}" within ${timeout}ms`
)
);
}, timeout);
}
this.worker.postMessage({ eventName, data, messageId });
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment