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

limp

v1.0.0

Published

An asyncronous control flow library

Downloads

5

Readme

Limp Build Status Coverage Status

Limp is a simple asynchronous control-flow library. It is meant to be a mostly drop-in replacement for the step library, and so has a very similar API. Why use it instead of step? While step is a useful library, Limp improves upon it in several ways.

  • Limp removes the synchronous behaviors. This is important, because accidentally returning a value in step was an easy way to accidentally advance to the next stage when asynchronous tasks were still running.

  • Limp throws exceptions when used incorrectly. This makes debugging incorrect usage of the library easier. Step would often keep running, but with hard-to-predict behaviors.

  • Adds several new features, such as this.await() for promise support, and this.rest() for multi-argument support in combination with other callback types.

Overview

The idea of Limp is that code is organized in 'stages', which are just functions. We advance from a stage when all callbacks (created by Limp) have been called. Values are then assembled, and passed to the next stage.

var limp = require('limp');

function getUsers(cb) {
  limp(
    function () {
      db.getCacheConnection(this.parallel());
      db.getAllUserIds(this.parallel());
    },
    function (err, cache_conn, user_ids) {
      if (err) { return cb(err); }
      var group = this.group();
      user_ids.forEach(function (id) {
        cache_conn.fetchUser(id, group());
      });
    },
    function (err, users_array) {
      if (err) { return cb(err); }
      cb(null, users_array);
    }
  );
}

Features

Features are provided through the this variable, which is injected into each stage function. Limp gives you callbacks with many different useful behaviors.

this

The this variable is a function that can be used as a callback for simple cases. It will pass all arguments it receives into the next stage. You shouldn't use this as a callback with any of the other callback types. Try using this.rest() if you'd like that kind of behavior.

limp(
  function () {
    someHttpService.request("/example", this);
  },
  function (err, response, body, buffer) {
    // ^^ Notice how all arguments given to the callback were passed into this stage.
  }
);

this.parallel()

The this.parallel() method will manufacture a new callback for you to use. Each one of these callbacks will take both the error and the first argument that it is called with, and pass them to the next stage. Multiple this.parallel() callbacks can be created, and each one will remember its placement relative to the others.

limp(
  function () {
    myDatabase.get("User", 123, this.parallel());
    fs.readFile("/opt/limp/README.md", this.parallel());
  },
  function (err, user_object, readme_contents) {
    // ^^ Each this.parallel() callback gets one argument in the next stage.
  }
);

this.group()

The this.group() method will create a factory function, that will itself produce new callbacks for you to use. Each callback created by a single this.group() function will be passed to the next stage in an array.

limp(
  function () {
    var group_a = this.group();
    all_user_ids.forEach(function (id) {
      myDatabase.get("User", id, group_a());
    });

    var group_b = this.group();
    url_list.forEach(function (url) {
      someHTTPService.post(url, group_b());
    });
  },
  function (err, users_array, http_responses) {
    // ^^ The users_array is in the same order as the ids in all_user_ids.
    //    SO is the http_responses array. Notice how they weren't mixed, because
    //    we created 2 groups.
  }
);

this.await(p)

The this.await(p) method waits for a promise. If it resolves to a value, that value is passed along to the next stage. If it rejects, the error will be passed along to the next stage, and a new error will be created if the promise rejected for no reason. This lets you easily merge promises into callback logic.

limp(
  function () {
    this.await(cacheDatabase.fetchUserPromise());
    this.await(cacheDatabase.fetchThingPromise());
  },
  function (err, user, thing) {
    // ^^ this.await() behaves similarly to this.parallel(), but with promises.
  }
);

this.rest()

The this.rest() method will create a callback that takes all arguments passed to it, and passes them to the next stage at the end of the argument list. This lets you mix the multi-argument behavior of the this callback with other callback types. A this.rest() callback should the last callback used in that stage.

limp(
  function () {
    fs.readFile("/home/user/blah.json", this.parallel());
    someHttpService.request("/something", this.rest());
  },
  function (err, blah_file, http_response, http_body, http_buffer) {
    // ^^ All the arguments passed to the this.rest() callback were pushed to
    //    the end of the argument list.
  }
);

this.errors

When a callback receives an error, that error is passed to the following stage as the first argument. If multiple callbacks error out, only the first one is passed as the first argument. If you want to see all errors, those are available in the this.errors array. This array has the same ordering as the arguments.

limp(
  function () {
    db.getUserObject(user_id, this.parallel()); // Errors in 5ms
    db.getTaskObject(task_id, this.parallel()); // Errors in 10ms
    db.getLikeObject(like_id, this.parallel()); // Returns successfully
  },
  function (err, user_obj, task_obj, like_obj) {
    // `err` is the user_obj error, since it came back first.
    // `this.errors` is [ user_err, task_err, null ].
  }
);