# mpmc

[![pipeline](https://img.shields.io/gitlab/pipeline/rasmusmerzin/mpmc/main)](https://gitlab.com/rasmusmerzin/mpmc/-/jobs)
[![coverage](https://img.shields.io/gitlab/coverage/rasmusmerzin/mpmc/main)](https://gitlab.com/rasmusmerzin/mpmc/-/jobs)
[![bundlesize](https://img.shields.io/bundlephobia/minzip/mpmc)](https://bundlephobia.com/package/mpmc)
[![version](https://img.shields.io/npm/v/mpmc)](https://www.npmjs.com/package/mpmc)
[![license](https://img.shields.io/npm/l/mpmc)](https://www.npmjs.com/package/mpmc)
[![downloads](https://img.shields.io/npm/dt/mpmc)](https://www.npmjs.com/package/mpmc)

Async multi-producer, multi-consumer FIFO queue communication utilies.
This is an experimental Typescript library for working with asynchronous streams
of data with a similar API to Rust standard module
[`mpsc`](https://doc.rust-lang.org/std/sync/mpsc/index.html).

The core building block of this library is function `onceChannel` which returns
a `Promise` with the `resolve` function.

```js
function onceChannel() {
  let resolve;
  const promise = new Promise((r) => (resolve = r));
  return [resolve, promise];
}
```

On top of `onceChannel` is built function `channel` which returns a
[`Sender`](src/sender.ts) and [`Receiver`](src/receiver.ts).

```ts
channel<T>(): [Sender<T>, Receiver<T>]
```

[`Sender`](src/sender.ts) and [`Receiver`](src/receiver.ts) classes loosely
follow the API of Rust
[`Sender`](https://doc.rust-lang.org/std/sync/mpsc/struct.Sender.html) and
[`Receiver`](https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver.html).

```ts
class Sender<T> {
  send(...arg: NonNullable<T>[]): boolean;
}

class Receiver<T> {
  recv(): Promise<T | null>;
  close(): boolean;
  forEach(f: (arg: T) => unknown): Promise<void>;
  collect(): Promise<T[]>;
}
```

`Sender.send` method takes non-nullable argument because `null` is used to
denote that `Receiver` has been closed. `Receiver` also implements
[`asyncIterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator)
protocol to enable it being used in a for loop.

```ts
for await (const msg of receiver) {
  // ...
}
```

## Related projects

- [RxJS](https://rxjs.dev) ‒ Reactive Extensions Library for JavaScript
- [Svelte](https://svelte.dev) ‒ Cybernetically enhanced web apps
- [React](https://reactjs.org) ‒ A JavaScript library for building user
  interfaces
