Created
February 10, 2022 23:27
-
-
Save steida/81c207163c24179065245a9e3882de93 to your computer and use it in GitHub Desktop.
Typed Web Worker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Typed Web Worker. | |
* | |
* type InputData = { name: string }; | |
* type OutputData = { nameLength: number } | |
* | |
* // main.js | |
* const worker = createTypedWorker<InputData, OutputData>(worker); | |
* | |
* // worker.js | |
* const worker = createTypedWorker<OutputData, InputData>(); | |
*/ | |
interface Subscription { | |
remove: () => void; | |
} | |
export interface TypedWorker<InputData, OutputData> { | |
postMessage: (data: InputData) => void; | |
// Ready for useSyncExternalStore. | |
// https://blog.saeloun.com/2021/12/30/react-18-usesyncexternalstore-api | |
onMessage: (listener: () => void) => Subscription; | |
getMessage: () => OutputData | null; | |
dispose: () => void; | |
} | |
export const createTypedWorker = <InputData, OutputData>( | |
worker: Worker = self as unknown as Worker | |
): TypedWorker<InputData, OutputData> => { | |
const listeners = new Set<() => void>(); | |
let data: OutputData | null = null; | |
const handleMessage = (e: MessageEvent) => { | |
if (e.data && e.data.type === "__typedWorker") { | |
data = e.data.data; | |
listeners.forEach((l) => l()); | |
} | |
}; | |
worker.addEventListener("message", handleMessage); | |
return { | |
postMessage(data) { | |
worker.postMessage({ type: "__typedWorker", data }); | |
}, | |
onMessage(listener) { | |
listeners.add(listener); | |
return { | |
remove: () => { | |
listeners.delete(listener); | |
}, | |
}; | |
}, | |
getMessage() { | |
return data; | |
}, | |
dispose() { | |
worker.removeEventListener("message", handleMessage); | |
}, | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment