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

nthen

v0.2.1

Published

Simple intuitive asynchronous control flow.

Downloads

549

Readme

nThen... Do this... nThen... Do that.

nThen is designed to be the most small, simple and intuitive asynchronous library.

How you used to do things

let x = synchronous_call();
let y = use(x);
let a = another_sync_call(x);          // Hey!
let b = yet_another_sync_call(x);      // these two could run at the same time!
let z = something_else_synchronous(b);
let c = last_synchronous_call(z);
do_next_job(c);

Ok so we learned that doing it that way is slow and we have asynchronous so we never have to be slow anymore.

The naive asynchronous approach

asyncCall(function (x) {
    let y = use(x);
    let aa;
    let cc;
    anotherCall(x, function (a) {
        aa = a;
        if (cc) { doNextJob(cc); }
    });
    yetAnotherCall(x, function (b) {
        somethingElse(b, function (z) {
            lastCall(z, function (c) {
                cc = c;
                if (aa) { doSomethingElse(aa); }
            });
        });
    });
});

That doesn't look like very much fun :( And to make matters worse, what happens if one of those functions never returns?

var to = setTimeout(function() { stopEverything(); }, 3000);

You can see where this is going.

nThen to the rescue

nThen allows you to do things in parallel by putting them in blocks and one block will not execute until all of the callbacks from the previous one have completed.

How do we know when all callbacks have been completed ? You wrap them using the waitFor function wrapper. Waitfor wraps a function, so the result of waitFor is another function and when that is called, all arguments are passed through to the function which was given to waitFor, however, nThen will block until all waitFors have been called.

You can use waitFor as many times as you want in an nThen block, you can even use a waitFor invocation inside of another waitFor invocation and it will keep the nThen block from terminating.

For example this works:

const nThen = require('nthen');
const Fs = require('fs');
nThen(function (waitFor) {
    Fs.readdir('/dev', waitFor(function (err, array) {
        if (err) { throw err; }
        if (array.indexOf('random') > -1) {
            Fs.stat('/dev/random', waitFor(function (err, stat) {
                if (err) { throw err; }
                console.log(stat);
            }));
        }
    }));
}).nThen(function (waitFor) {
    console.log('completed');
});

Using nThen to sequencialize a list of async operations

Sometimes you want to do a variable number of things in sequence. Suppose you wanted to stat every file in the /dev directory but you want to do them one at a time.

You can loop over all files using nThen to access each one sequencially like this:

const nThen = require('./index.js');
const Fs = require('fs');
var nt = nThen;
Fs.readdir('/dev', function (err, array) {
    if (err) { throw err; }
    array.forEach(function (x) {
        nt = nt(function (waitFor) {
            Fs.stat('/dev/' + x, waitFor(function (err, stat) {
                if (err) { throw err; }
                console.log(stat);
            }));
        }).nThen;
    });
    nt(function (waitFor) {
        console.log('done');
    });
});

Nested nThen

You can use multiple levels of nesting of nThen, for example you might use a loop of async operations inside of one block of larger nThen chain, like this. Notice waitFor can be used without a wrapped function.

const nThen = require('./index.js');
const Fs = require('fs');
let fileList;
nThen(function (waitFor) {
    Fs.readdir('/dev', waitFor(function (err, array) {
        if (err) { throw err; }
        fileList = array;
    }));
}).nThen(function (waitFor) {
    let nt = nThen;
    fileList.forEach(function (x) {
        nt = nt(function (waitFor) {
            Fs.stat('/dev/' + x, waitFor(function (err, stat) {
                if (err) { throw err; }
                console.log(stat);
            }));
        }).nThen;
    });
    // This line is what will hold open this nThen block until
    // all of the files in fileList have been stated.
    nt(waitFor());
}).nThen(function (waitFor) {
    console.log('done');
});

orTimeout

You can end your nThen chain with an orTimeout call which will abort the execution of the nThen chain if the execution takes more than a given number of milliseconds.

const nThen = require('./index.js');
nThen(function (waitFor) {
    let done = waitFor(function () { console.log('this never gets invoked'); });
    if (1 === 2) {
        // never happens
        done();
    }
}).nThen(function (waitFor) {
    console.log('so we never get to this point');
}).orTimeout(function () {
    console.log('timed out after 1 second');
}, 1000);

Details

  • If you do not call waitFor at all within an nThen block, the block will exit synchronously
  • You can use waitFor without wrapping any callback function, it works fine with nothing
  • nThen is fully ECMA-5 compatible, it is also compatible with flow typing system
  • nThen does operations in sequence (no parallelism), if you'd like to do n parallel operations check out saferphore

License

Public Domain or MIT license, as you wish.

Contact

@[email protected]