npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

promise-mix

v1.8.4

Published

Node module with some useful Promise composition functionalities.

Downloads

34

Readme

buddy pipeline Coverage Status Inline docs npm version Maintainability

Promise Mix

Logo

This module contains a lot of extensions to default Node.js Promise.

Check out the full A-Z list of extensions!

How?

Install

~$ npm install promise-mix

Import

To use the extensions, simply import the module in your script:

require('promise-mix');

or

import 'promise-mix';

Why?

While using promises I often find it hard to orchestrate them correctly and in an elegant, readable way. Thus I decided to make some extension to the basic Promise library in order to put some order in my code.

For example, when having to return a structured JSON composed with the results of different Promise I'd usually just build a Promise chain like this:

Promise.resolve('first promise result')
    .then((res1) => {
        return Promise.resolve('second promise result')
            .then((res2) => {
                return { res1, res2 };
            });
    })
    .then((res12) => {
        return Promise.resolve('third promise result')
            .then((res3) => {
                return {...res12, res3};
            });
    })
    .then((output) => {
        res.send(output)
    }).catch(next);
/**
 *  this would return to the caller:
 * 
 *      { 
 *          res1: 'first promise result', 
 *          res2: 'second promise result', 
 *          res3: 'third promise result' 
 *      }
 * /

With the aggregate extension, it'd be much more straight forward and clean to obtain the same result:

Promise.aggregate({
    res1: Promise.resolve('first promise result'),
    res2: Promise.resolve('second promise result'),
    res3: Promise.resolve('third promise result'),
})
.then((output) => {
    res.send(output)
}).catch(next);
// this would return the same output as above.

Check out all the extensions for more useful combination methods.

What?

This module adds four basic composition functions to the basic Promise Object:

  1. aggregate puts the results of a series of Promise into an aggregate object and passes it downstream as a single promise result.

    Promise.aggregate({
        cats: Promise.resolve(['Felix', 'Garfield']),
        dogs: Promise.resolve(['Rex', 'Lessie']),
        turtles: Promise.resolve([]),
        fish: Promise.resolve('Nemo')
    })
    .then(({ cats, dogs, fish, turtle }) => {
        // { cats, dogs, fish, turtle } = { cats: ['Felix', 'Garfield'], dogs: ['Rex', 'Lessie'], fish: 'Nemo', turtle: [] }
    });
  2. compose like aggregate, but each item of the input must be a function returning a Promise. Results from previous promises will be passed down as parameters to successive functions:

    Promise.combine({
        cats: () => { return Promise.resolve(['Felix', 'Garfield'])),
        dogs: ({ cats }) => { return Promise.resolve(['Rex', 'Lessie']) },
        turtles: ({ cats, dogs }) => { return Promise.resolve([]) },
        fish: ({ cats, dogs, turtle }) => { return Promise.resolve('Nemo') },
        everyone: ({ cats, dogs, turtle, fish }) => { return Promise.resolve({ cats, dogs, turtle, fish }) }
    })
    .then(({ cats, dogs, fish, turtle, everyone }) => {
        // { cats, dogs, fish, turtle, everyone } = { cats: ['Felix', 'Garfield'], dogs: ['Rex', 'Lessie'], fish: 'Nemo', turtle: [], everyone: { cats: ['Felix', 'Garfield'], dogs: ['Rex', 'Lessie'], fish: 'Nemo', turtle: [] } }
    });
  3. merge merges the results of an array of promises into a single flat array:

    Promise.merge([
        Promise.resolve(['Felix', 'Garfield']),
        Promise.resolve(['Rex', 'Lessie']),
        Promise.resolve([]),
        Promise.resolve(['Nemo'])
    ])
    .then((results) => {
        // results = ['Felix', 'Garfield', 'Rex', 'Lessie', 'Nemo']
    });
  4. reduce accepts an array of functions returning promises and returns the result of the last promise in the array. Each promise result is passed as an argument to the next function in the array:

    Promise.reduce([
        () => { reutrn Promise.resolve(['Felix', 'Garfield']) },
        (cats) => { return Promise.resolve(['Rex', 'Lessie']) },
        (dogs) => { return Promise.resolve(dogs) },
        (turtles) => { return Promise.resolve(turtles) }
    ])
    .then((results) => {
        // results = ['Rex', 'Lessie']
    });

... And many more! Check out the full A-Z list of extensions!

Version History

1.0.X: First version with few patches, final patch 1.0.7.

1.1.X: New Features:

  1. fCombine and fReduce which behave like combine and reduce, but make use of functions in the format (pars, callback(err, val)) instead of functions returning promises. This helps integrate async library functions that make use of callbacks instead of Promises.

  2. All functions now accept a second parameter which will be used as initial value for the sequence. See tests and documentation for some example.

1.2.X: New Features:

Extensions can now be concatenated with instance-specific functions: _aggregate, _combine, _fCombine, _merge, _reduce, _fReduce. These concatenation functions help switch composition context and structure on the go, but might end up confusing as for the value passed downstream. See tests for some working examples.

1.3.X: New Features:

  1. Added dev warnings and errors for concatenation special cases: _aggregate and _combine will have non-object donwstreams assigned to an _init variable in the aggregation object.

  2. Added mux and deMux functionality to mix several promises from an array or an object of inputs as if it were one. See tests for some cool example!

1.4.X: New Features:

  1. Added _aside concatenation to execute side-operations alongside the downstream without affecting the downstream itself, even ignoring errors if desired.

  2. Added or, and and xor methods to handle logical composition of a sequence of Promises's results. For examble the or operator doesn't even execute a successive Promise if any previous one succeeds, while and doesn't executre successive Promises of a failed one. Each logical operation "fails" if the downstream is undefined or if a given check function on the result is not met.

  3. Added _or, _and and _xor concat methods to chain logical block building with downstream data from other promises. These also work with mux-ed Promises.

1.5.X: New Features:

  1. Added some utility functions which can be useful to add expressivity to Promise chains and shorten some steps.

  2. Added _filter and _shuffle methods to muxed Promises. The _filter method accept a filtering function and sets to undefined all the filtered out downstreams (the function should return true for passing downstreams only). Chaining a _clean() after the deMux will finally remove the filtered-out undefined items from the downstream. The _shuffle method simply shuffles the Promises in the mux pool (be it an Array or an Object) and keeps the new shuffled pool for chaining.

1.6.X: New Features:

  1. Now base mix functions (aggregate, combine, merge, reduce) may accept some non-Promise values as well, this way you can build outputs more cleanly and you can skip writing chains to just return Promise.resolve(val).

  2. Now combine and reduce may accept functions which do not return Promises, but "static values", so you don't have to return a Promise.resolve(val) in your function.

1.7.X: New Features:

  1. Inverted _when parameters order: check comes first and function to execute if check is true comes second.

  2. Added _ifElse function that checks a condition, then executes an if-function if the check returns true, or an elseFunction if the check returns false.

  3. Added _exists function which is like _check but only accepts the error which is thrown if the downstream is evaluated to false.

1.8.X: Flexible Mapping! New Features:

  1. Introduced the concept of Operation to wrap any argunet of basic composition functions (aggregate, combine, fCombine, merge, reduce and fReduce). This way you can now put anything you like as items (or fields) of the composition map.

  2. As a result of point 1 aggregate is now deprecated as its behaviour is now replicable with a combine.

  3. Operations also work as _ifElse and _when "effects" (the check function is still a plain Function). Same goes for the _aside function which is now a generic Operation.

  4. Converstion of callback-style Functions into Promises with promisify is now at Operation level, so each base function (aggregate, combine, fCombine, merge, reduce and fReduce) now has a promisify optional flag (last optional parameter) which enables/disables the promisify conversion for all the given functions. If you wish to promisify only a specific step of your composition map, then you can create an Operation passing your callback function and the promisify flag true to its constructor. This change makes fReduce and fCombine obsolete, but they're kept as more direct method to handle promisified functions.