Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jamiemccrindle/axax

Async Iterator Extensions for JavaScript e.g. map, reduce, filter, flatMap, etc.
https://github.com/jamiemccrindle/axax

Last synced: 3 months ago
JSON representation

Async Iterator Extensions for JavaScript e.g. map, reduce, filter, flatMap, etc.

Awesome Lists containing this project

README

        

# Async Iterator Extensions

A library of async iterator extensions for JavaScript including ```map```, ```reduce```,
```filter```, ```flatMap```, ```pipe``` and [more](https://github.com/jamiemccrindle/axax/blob/master/docs/API.md#functions).

# Installation

```bash
npm install axax # or yarn add axax
```

# Why Axax?

Async iterators are a useful way to handle asynchronous streams. This library adds a number
of utility methods similar to those found in lodash, underscore, Ramda or RxJs.

## es5 vs esnext

Axax contains both transpiled es5 code as well as esnext code, the difference being that
esnext uses the native ```for await``` syntax. In nodejs 10.x that gives approximately a 40% speedup.

```javascript
// use es5 if you want to support more browsers
import { map } from "axax/es5/map";

// use esnext if you're only using node 10.x or supporting very new browsers
import { map } from "axax/esnext/map";
```

# Reference Documentation

* [API Reference](https://github.com/jamiemccrindle/axax/blob/master/docs/API.md)

# Examples

## fromEvent

```fromEvent``` turns DOM events into an iterable.

```javascript
import { fromEvent } from "axax/es5/fromEvent";

const clicks = fromEvent(document, 'click');

for await (const click of clicks) {
console.log('a button was clicked');
}
```

## pipe, map, filter, fromLineReader

```fromLineReader``` turns a NodeJS LineReader into an async iterable.
The example below prints the lines from a file in upper case after
filtering out the empty ones.

```javascript
// create the line reading async iterable
const lines = fromLineReader(
require("readline").createInterface({
input: require("fs").createReadStream("./data/example.txt")
})
);

// create a filter that removes empty lines
const notEmpty = filter(line => line.length > 0);

// convert to uppercase
const toUpperCase = map(line => line.toUpperCase());

// go through each of the non empty lines
for await (const line of pipe(notEmpty, toUpperCase)(lines)) {
console.log(line);
}
```

## Subject

```Subject``` makes it easy to turn stream of events into an iterable. The code below
is essentially how ```fromEvent``` was implemented.

```javascript
import { Subject } from "axax/es5/subject";

const subject = new Subject();

// set up a callback that calls value on the subject
const callback = value => subject.onNext(value);

// attach the callback to the click event
document.addEventListener('click', callback);

// remove the callback when / if the iterable stops
subject.finally(() => document.removeEventListener('click', callback));

// go through all the click events
for await (const click of subject.iterator) {
console.log('a button was clicked');
}
```

# Avoiding leaks

It's possible to have an async iterator leak if it never returns a value e.g.:

```javascript
const subject1 = new Subject();
const subject2 = new Subject();

async function* neverEnds() {
try {
for await(const i of subject2.iterator) {
yield i;
}
} finally {
console.log("never called")
}
}

async function* run() {
for await(const i of merge(subject1.iterator,neverEnds())) {
break;
}
}

run()
subject1.onNext(1)
```

If you need to be able to cancel async iterators that may never return values,
consider Rx or regular Observables for now.

(Thanks to [@awto](https://github.com/awto) for the example)