Skip to content

Instantly share code, notes, and snippets.

@trvswgnr
Last active August 22, 2023 07:09
Show Gist options
  • Select an option

  • Save trvswgnr/f392b36ca153e738cf72e8f407099322 to your computer and use it in GitHub Desktop.

Select an option

Save trvswgnr/f392b36ca153e738cf72e8f407099322 to your computer and use it in GitHub Desktop.
easy multithreading w/ worker threads nodejs typescript
import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
// Worker thread
if (!isMainThread) {
const workerFunction: (input: any) => any = eval(workerData.workerFunction);
const result = workerFunction(workerData.input);
parentPort?.postMessage(result);
}
// Main thread
class ParIterator<T, R> {
private workers: Worker[] = [];
private tasks: T[] = [];
private results: R[] = [];
private workerFunction: (input: T) => R;
constructor(workerFunction: (input: T) => R, inputs: T[], numWorkers: number) {
this.workerFunction = workerFunction;
this.tasks = inputs;
this.startWorkers(numWorkers);
}
private startWorkers(numWorkers: number): void {
for (let i = 0; i < numWorkers; i++) {
const worker = new Worker(__filename, {
workerData: { workerFunction: this.workerFunction.toString() },
});
worker.on('message', (result) => {
this.results.push(result);
if (this.tasks.length > 0) {
worker.postMessage(this.tasks.shift());
} else {
worker.terminate();
}
});
worker.on('error', (error) => {
throw error;
});
this.workers.push(worker);
}
}
async forEach(callback: (value: R) => void): Promise<void> {
for (const worker of this.workers) {
if (this.tasks.length > 0) {
worker.postMessage(this.tasks.shift());
}
}
while (this.results.length < this.tasks.length) {
await new Promise((resolve) => setTimeout(resolve, 100));
}
this.results.forEach(callback);
}
async map(): Promise<R[]> {
for (const worker of this.workers) {
if (this.tasks.length > 0) {
worker.postMessage(this.tasks.shift());
}
}
while (this.results.length < this.tasks.length) {
await new Promise((resolve) => setTimeout(resolve, 100));
}
return this.results;
}
}
Array.prototype.parIter = function<T, R>(this: T[], workerFunction: (input: T) => R, numWorkers: number): ParIterator<T, R> {
return new ParIterator(workerFunction, this, numWorkers);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment