Select in JavaScript

JavaScript doesn’t have built-in support for channels or goroutines like Go does. However, we can simulate similar behavior using Promises and async/await. Here’s how we can translate the select functionality:

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

async function main() {
    // For our example we'll use Promises to simulate channels
    const c1 = delay(1000).then(() => "one");
    const c2 = delay(2000).then(() => "two");

    // Each Promise will resolve after some amount of time, 
    // to simulate e.g. blocking operations executing concurrently.

    // We'll use Promise.race to await both of these values
    // simultaneously, printing each one as it arrives.
    for (let i = 0; i < 2; i++) {
        const result = await Promise.race([c1, c2]);
        console.log("received", result);

        // Remove the resolved promise from the race
        if (result === "one") {
            c1 = new Promise(() => {});
        } else {
            c2 = new Promise(() => {});
        }
    }
}

main();

In this JavaScript version, we use Promises to simulate the behavior of channels. The delay function creates a Promise that resolves after a specified number of milliseconds, simulating the time.Sleep in the original code.

Instead of goroutines, we create two Promises (c1 and c2) that resolve after 1 and 2 seconds respectively.

The select statement is simulated using Promise.race, which returns a Promise that resolves or rejects as soon as one of the Promises in the iterable resolves or rejects.

We use a loop to receive both values, similar to the original code. After each iteration, we replace the resolved Promise with a never-resolving Promise to ensure we get both results.

To run this code:

$ node select.js
received one
received two

Note that the total execution time is only ~2 seconds since both the 1 and 2 second delays execute concurrently.

This example demonstrates how to handle multiple asynchronous operations in JavaScript, waiting for whichever one completes first. While it’s not an exact equivalent of Go’s select, it provides similar functionality in terms of handling concurrent operations.