Worker Pools in TypeScript

Our example demonstrates how to implement a worker pool using asynchronous functions and promises.

import { setTimeout } from 'timers/promises';

// This is our worker function. It will receive jobs from the jobs array
// and send the corresponding results to the results array.
// We'll use a setTimeout to simulate an expensive task.
async function worker(id: number, jobs: number[], results: number[]): Promise<void> {
    for (const job of jobs) {
        console.log(`worker ${id} started job ${job}`);
        await setTimeout(1000);
        console.log(`worker ${id} finished job ${job}`);
        results.push(job * 2);
    }
}

async function main() {
    const numJobs = 5;
    const jobs: number[] = [];
    const results: number[] = [];

    // Create our jobs
    for (let j = 1; j <= numJobs; j++) {
        jobs.push(j);
    }

    // Start 3 worker functions
    const workers = [];
    for (let w = 1; w <= 3; w++) {
        workers.push(worker(w, jobs, results));
    }

    // Wait for all workers to complete
    await Promise.all(workers);

    console.log('Results:', results);
}

main().catch(console.error);

In this example, we’re using asynchronous functions and promises to simulate concurrent behavior. Here’s a breakdown of what’s happening:

  1. We define a worker function that takes an ID, a jobs array, and a results array. It processes each job, simulates work with a 1-second delay, and adds the result to the results array.

  2. In the main function, we create our jobs and results arrays.

  3. We start three worker functions, each processing the same jobs array and writing to the same results array.

  4. We use Promise.all to wait for all workers to complete before logging the results.

To run this program, save it as worker-pools.ts and use ts-node (assuming you have TypeScript and ts-node installed):

$ npx ts-node worker-pools.ts
worker 1 started job 1
worker 2 started job 2
worker 3 started job 3
worker 1 finished job 1
worker 2 finished job 2
worker 3 finished job 3
worker 1 started job 4
worker 2 started job 5
worker 1 finished job 4
worker 2 finished job 5
Results: [ 2, 4, 6, 8, 10 ]

This program demonstrates how to distribute work across multiple asynchronous functions. Despite doing about 5 seconds of total work, the program only takes about 2 seconds to complete because there are 3 workers operating concurrently.

Note that while this example simulates concurrent behavior, JavaScript (and by extension, TypeScript) is single-threaded. For true parallelism in JavaScript environments, you would need to use Web Workers in a browser context or Worker Threads in Node.js.