UNPKG

axax

Version:

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).

134 lines (93 loc) 3.38 kB
# 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)