const Worker = globalThis.Worker ?? (await import('node:worker_threads')).Worker
-type Thread = {
- worker: Worker,
- tasks: any[],
- isAvailable: boolean
+class Thread {
+ worker: Worker
+ tasks: any[]
+ get isAvailable () { return this.tasks.length === 0 }
+
+ constructor (url: string | URL) {
+ this.worker = new Worker(new URL(url, import.meta.url))
+ this.worker.addEventListener('message', (event) => {
+ if (this.tasks.length > 0) {
+ this.worker.postMessage(this.tasks.shift())
+ }
+ })
+ this.tasks = new Array()
+ }
}
+
/**
* Assigns a Web Worker to process data. Creates a new one if none are available.
*
constructor (url: string | URL) {
this.#url = new URL(url, import.meta.url)
this.#threads = [...Array(navigator.hardwareConcurrency)]
- this.#threads = this.#threads.map(() => {
- return {
- worker: new Worker(this.#url),
- tasks: new Array(),
- get isAvailable () { return this.tasks.length === 0 }
- }
- })
+ this.#threads = this.#threads.map(() => { return new Thread(this.#url) })
}
async work (data: object): Promise<any> {
- return new Promise((resolve) => {
- const thread = this.#threads.reduce((curr, next) => {
- return (next.tasks.length < curr.tasks.length)
- ? next
- : curr
- })
- thread.tasks.push(data)
- thread.worker.postMessage(thread.tasks.shift())
- thread.worker.onmessage = (event: any) => {
- if (thread.tasks.length > 0) {
- thread.worker.postMessage(thread.tasks.shift())
- }
+ const thread = this.#threads.reduce((curr, next) => {
+ return (next.tasks.length < curr.tasks.length)
+ ? next
+ : curr
+ })
+ thread.tasks.push(data)
+ thread.worker.postMessage(thread.tasks.shift())
+ return new Promise(resolve => {
+ thread.worker.addEventListener('message', (event: any) => {
resolve(event.data)
- }
+ }, { once: true })
})
}
}