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

continuate

v0.8.2

Published

A wrapper to convert regular functions to continuation-passing style

Downloads

3

Readme

continuate

Build Status

A wrapper to convert regular functions to continuation-passing style.

Usage

//regular divide function which throws error if second arg is 0
function divide(a, b) {
  if (b === 0) {
    throw Error('b is 0');
  }
  return a / b;
}

var cps = require('continuate');

var cpsDivide = cps(divide);

cpsDivide(46, 2, function (err, data) {
  console.assert(data === 23);
});

//it provides error to callback
cpsDivide(1, 0, function (err, data) {
  console.assert(err === true);
});

Description

To avoid callback hell you usually work with modules like async and its methods. Assume that you have a pretty complex function built upon async#auto or async#parallel, whatever. Here we read two data sources and pass data to data-handlers. If data-handlers are pretty complex we will eventually want them to be wrapped in try/catch to avoid sudden failing of our app:

var async = require('async');

function handleData1(dbData) {
  // very complex logic to rebuild dbData
}

function handleData2(webServiceData) {
  // very complex logic to rebuild webServiceData
}

async.auto({
  'dataSource1': [function (callback) {
    readDatabase(callback);
  }],
  'dataSource2': [function (callback) {
    getDataFromWebService(callback);
  }],
  'actionsWithData1': ['dataSource1', function (callback, results) {
    try {
      var data = handleData1(results.dataSource1);
    } catch (err) {
      return callback(err);
    }
    callback(null, data);
  }],
  'actionsWithData2': ['dataSource2', function (callback, results) {
    try {
      var data = handleData2(results.dataSource2);
    } catch (err) {
      return callback(err);
    }
    callback(null, data);
  }],
});

Here we can see that code is not DRY and looks pretty ugly. We can rewrite those handler in continuation-passing style (CPS) right away but imaging situation when you need those handlers as a regular functions, say in synchronous code. You will not want additional callback level in your neat synchronous code.

Instead we can rewrite handling of data in prettier way using continuate module. It is an utility you can use to easily convert regualr functions to CPS:

var async = require('async');
var cps = require('continuate');

//...

async.auto({
  'dataSource1': [function (callback) {
    readDatabase(callback);
  }],
  'dataSource2': [function (callback) {
    getDataFromWebService(callback);
  }],
  'actionsWithData1': ['dataSource1', function (callback, results) {
    var cpsStyle_handleData1 = cps(handleData1);
    //Now it provides error and result in the callback
    cpsStyle_handleData1(results.dataSource1, callback);
  }],
  'actionsWithData2': ['dataSource2', function (callback, results) {
    cps(handleData2)(results.dataSource2, callback);
  }],
});

And we have neat and descriptive logic without changing original handleData1 and handleData2 functions so we can reuse them in regular and CPS-code.

Note, that when you use CPS, functions doesn't become 'asynchronous'. They just provide their results in callbacks.

Consider this example:

var cps = require('continuate');

function add(a, b) { return a + b; }

var cpsAdd = cps(add);
cpsAdd(1, 42, function (err, data) {
  console.assert(data === 43);
});

Since it only returns new function it can be also used with methods. Simple Function.prototype.bind helps:

var cps = require('continuate');

var object = {
  counter: 0,
  add: function (x) { return this.count += x; }
}

var cpsAdd = cps(object.add.bind(object));
cpsAdd(1, function (err, res) {
  console.assert(res === 1);
});