Link Search Menu Expand Document

Selecting a Channel operation

Sometimes we want to race several channel operations against each other, and select the first operation completed (aborting the other operations).

To do that, async_channels provides the select function (and select tagged template)

Example (function):

import { Channel, select } from "...";
const done = new Channel();
const input = new Channel();

(async () => {
  while (true) {
    const [val, ch] = await select([done, input]);
    if (ch === done) return;
    console.log("Got: ", val);
  }
})().finally(() => console.log("Loop completed"));

await input.send("Hello"); // => Got: Hello
await input.send("world"); // => Got: world
done.close();

// This will not resolve, because no one is waiting for values from input.
const p = input.send("goodbye").catch((e) =>
  console.log("Expected error caught:", e.message)
);

// This will cause the above `input.send()` to reject.
input.close(); // => Expected error caught: Send on closed channel
await p; // => Loop completed

Example (tagged template):

import { Channel, tagged } from "...";
const { select } = tagged;
const done = new Channel();
const input = new Channel();

(async () => {
  let cont = true;
  while (cont) {
    // Because the handler for `done` is executed inside a function, you cannot `return` or `break` from it.
    await select`
      case ${done}: ${() => cont = false}
      case ${input}: ${(val) => console.log("Got:", val)}
    `;
  }
})().finally(() => console.log("Loop completed"));

await input.send("Hello"); // => Got: Hello
await input.send("world"); // => Got: world
done.close();

// This will not resolve, because no one is waiting for values from input.
const p = input.send("goodbye").catch((e) =>
  console.log("Expected error caught:", e.message)
);

// This will cause the above `input.send()` to reject.
input.close(); // => Expected error caught: Send on closed channel
await p; // => Loop completed

Previous - Closing Channels