0.0.3 • Published 7 years ago

@landonschropp/promise-pipe v0.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
7 years ago

promisePipe

promisePipe is a nifty little pipe library along the same lines as Ramda's pipe method. Unlike pipe, promisePipe operates on promises instead of functors.

Installation

To install the package:

yarn add @landonschropp/promise-pipe

Alternative, you can use NPM:

npm install @landonschropp/promise-pipe

Why Does This Exist?

Ramda's pipe allows you to combine multiple functions together in a point-free style like this:

let averageHeight = R.pipe(
  R.map(R.prop('height')),
  R.median
);

averageHeight([
  { height: 7 },
  { height: 6 },
  { height: 5 }
]); // => 6

This style allows you to compose functions. It gives you the ability to think declaratively rather than imperatively.

This works great for pure functions, but it starts to get a little tedious when you need to deal with side effects and asynchronicity. Let's extend the example above to call an API operate on the result using Fluture.

function fetchPokemon(id) {
  return Future((reject, resolve) => {
    fetch(`http://pokeapi.co/api/v2/pokemon/${ id }`)
      .then(response => response.json())
      .then(resolve, reject);
  });
}

let averagePokemonHeight = R.pipe(
  R.map(fetchPokemon),
  R.curry(Future.parallel)(Infinity),
  R.map(R.map(R.prop('height'))),
  R.map(R.median)
);

averagePokemonHeight([1, 4, 7]).fork(console.log, console.log);
// => 6

JavaScript already has a built in alternative to containers: promises! While promises are not technically functors, they're still a really convenient way to pass data through applications. The example above can be rewritten to use promisePipe:

function fetchPokemon(id) {
  return fetch(`http://pokeapi.co/api/v2/pokemon/${ id }`)
    .then(response => response.json());
}

let averagePokemonHeight = promisePipe(
  R.map(fetchPokemon),
  R.bind(Promise.all, Promise),
  R.map(R.prop('height')),
  R.median
);

averagePokemonHeight([1, 4, 7]).then(console.log);
// => 6

This allows you to build piped functions as you normally would. If the function returns a promise, that promise's value is piped into the next function. If it doesn't, it's value is automatically wrapped in a promise.

A promisePipe function is even cleaner when called inside of a async function.

async function averagePokemonHeight() {
  return await averagePokemonHeight([1, 4, 7]);
}
0.0.3

7 years ago