Hacker News new | ask | show | jobs
by graup 959 days ago
I really like Go channels, and I was looking for something like this in JS.

One of the earlier implementations is this one, albeit not maintained anymore: https://github.com/NodeGuy/channel I think I prefer its more concise API, e.g. for select (https://github.com/NodeGuy/channel/blob/main/API.md#examples). ts-chan's API looks a bit too verbose to my taste.

Here's an example from ts-chan:

  import {recv, Chan, Select} from 'ts-chan';

  const ch1 = new Chan<number>();
  const ch2 = new Chan<string>();

  void sendsToCh1ThenEventuallyClosesIt();
  void sendsToCh2();

  const select = new Select([recv(ch1), recv(ch2)]);
  for (let running = true; running;) {
    const i = await select.wait();
    switch (i) {
    case 0: {
      const v = select.recv(select.cases[i]);
      if (v.done) {
        running = false;
        break;
      }
      console.log(`rounded value: ${Math.round(v.value)}`);
      break;
    }
    case 1: {
      const v = select.recv(select.cases[i]);
      if (v.done) {
        throw new Error('ch2 unexpectedly closed');
      }
      console.log(`uppercase string value: ${v.value.toUpperCase()}`);
      break;
    }
    default:
      throw new Error('unreachable');
    }
  }

I would consider rewriting the API to something like this:

  import { receive, Channel, select } from 'ts-chan';

  const ch1 = new Channel<number>();
  const ch2 = new Channel<string>();

  void sendsToCh1ThenEventuallyClosesIt();
  void sendsToCh2();

  for (let running = true; running;) {
   switch(await select([receive(ch1), receive(ch2)])) {
      case ch1: {
        if (ch1.done) {
          running = false;
          break;
        }
        console.log(`rounded value: ${Math.round(ch1.value)}`);
      }
      case ch2: {
        if (ch1.done) {
          throw new Error('ch2 unexpectedly closed');
        }
        console.log(`uppercase string value: ${ch2.value.toUpperCase()}`);
        break;
      }
    }
  }
1 comments

I've been considering adding a `select` function, but I was concerned with the overhead of recreating the select case each time, and wanted to reserve it for a time once I've mulled over my options (I'm aiming to avoid making breaking changes, even though it's pre-v1).

With receives, there's a value attached, and that presents some difficulties regarding typing (for TypeScript).

You have given me an idea, however: I _might_ be able to wrangle together a mechanism that avoids making it a two-step deal (get the index, then resolve the type). It'd probably support only a subset of the functionality, though.

It's on my list to add a simple example to the README using the `Chan` class. Communicating with a single channel (with or without abort support) is very simple, and I'm happy with the API for that.

In addition to my other comment, I agree with the parent here. I appreciate the attempt to mirror golang’s naming, but it would be vastly more readable if you used Channel instead of Chan, etc.