Closing Channels in TypeScript

Closing a channel in TypeScript is not a built-in feature as it is in some other languages. However, we can simulate this behavior using a boolean flag. This can be useful to communicate completion to the channel’s receivers.

In this example, we’ll use a jobs queue to communicate work to be done from the main function to a worker function. When we have no more jobs for the worker, we’ll set a closed flag to true.

import { EventEmitter } from 'events';

function main() {
    const jobs = new EventEmitter();
    const jobQueue: number[] = [];
    let closed = false;

    // Here's the worker function. It repeatedly receives
    // from jobs with jobs.on('job', (j) => {...}). We use
    // the closed flag to determine when all jobs have been processed.
    // We use a Promise to notify when we've worked all our jobs.
    const workerPromise = new Promise<void>((resolve) => {
        jobs.on('job', (j: number) => {
            console.log("received job", j);
        });

        jobs.on('end', () => {
            console.log("received all jobs");
            resolve();
        });
    });

    // This sends 3 jobs to the worker over the jobs
    // event emitter, then sets the closed flag to true.
    for (let j = 1; j <= 3; j++) {
        jobQueue.push(j);
        console.log("sent job", j);
    }
    closed = true;
    console.log("sent all jobs");

    // Process the job queue
    while (jobQueue.length > 0) {
        const job = jobQueue.shift();
        if (job !== undefined) {
            jobs.emit('job', job);
        }
    }
    jobs.emit('end');

    // We await the worker using the Promise we created earlier.
    workerPromise.then(() => {
        // In TypeScript, we don't have the concept of reading from a closed channel.
        // Instead, we can check our closed flag.
        console.log("jobs closed:", closed);
    });
}

main();

When you run this TypeScript code, you should see output similar to this:

sent job 1
sent job 2
sent job 3
sent all jobs
received job 1
received job 2
received job 3
received all jobs
jobs closed: true

In this TypeScript version, we’ve used an EventEmitter to simulate the behavior of a channel. The closed flag is used to indicate when no more jobs will be sent. The worker function uses event listeners to process jobs and detect when all jobs have been sent.

This example demonstrates how to implement a similar pattern in TypeScript, even though the language doesn’t have built-in channels like some other languages do.