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

callback-bender

v1.0.3

Published

A utility package for converting different kinds of javascript callbacks into various promise types.

Downloads

66

Readme

callback-bender

npm version A utility package for converting different kinds of javascript callbacks into various promise types. You can wrap functions that work with callbacks into functions that return promises and can be used with async/await. If this does help you, please consider making a tiny donation here. 🤝

About Project

Working with javascript can be frustrating for many reasons, one of them is the callback hell. In addition to callbacks making code uglier and longer, they also make it hard to work with promises or async/await. The goal of this project is to provide wrapper functions that transform these functions into functions that return native promises.

Most Common Use Cases For Callback Converters

When working with NodeJS, you will encounter many Node API functions that work with callbacks. for example, many if not all functions in the 'fs' module use EFC style callbacks. Though there is a utility package for converting them, the utility package is part of nodejs and not available on other platforms. On the other hand, a lot of the examples online do not use the promisified syntax.

Why Callback Bender?

  • Uses standard, friendly syntax const wrapped = bend.efc.single(fs.readdir);
  • Unified syntax across all your projects
  • Supports both Continuation Passing callbacks (normal) and Error-First callbacks (EFC or node style)
  • Supports wrapping callbacks that accept multiple/single/no argument(s)
  • Is pretty small (3KB even before minification)
  • Provides many module formats (.mjs, es6, IIFE or script tag, all in the lib folder)
  • Provides type definitions
  • Provides typescript version (lib folder)
  • Is tested and passing all tests

Callback Types

There are mainly two types of callbacks, CP and EFC.

CP:

Continuation Passing callbacks are callbacks that do not accept errors (at least not as the first parameter).

// API code:
function foo(a, b, cb){
    .
    .
    .
    cb(a+b);
}

// your code:
foo(1,2,(res)=>{...});

EFC:

Error-First callbacks are callbacks that accept error as their first parameter, this style is most commonly used in NodeJS.

// API code:
function foo(a, b, cb){
    .
    .
    .
    if(error){
    cb(error);
    }else{
    cb(undefined, a+b);
    }
}

// your code:
foo(1,2,(err, res)=>{
    if(err){
    ...
    } else {
    ...
    }
});

Getting Started

This library uses and depends on es6, so keep that in mind. There are no package dependencies.

npm : 

note: the default file in the package uses CommonJS (require style, mainly for node), if you need ES6 Module version (try this if in doubt) or .mjs or IIFE (var name is callback_bender) please import or use files from lib folder!

npm i callback-bender

Format:

<bend.callback_type.return_count>

example: bend.cp.multiple(...)
         bend.efc.none(...)

example: const wrapped = bend.efc.single(fs.readdir);

note: CP is aliased as normal e.g. bend.normal.none(...) , EFC is aliased as node e.g. bend.node.none(...)

Why are there different versions of return types?

A callback can accept more than one argument, e.g. (a,b,c) => {} but async/await format expects one return to store in your variable,  e.g. let foo = await something(); This is why we need to use different wrappers for different callbacks.

Now that we covered the basics, let's see some examples:

import:

from the default file in package:

const bend = require('callback_bender');
// import bend from 'callback_bender/lib/cb.es6'; for es6 or browser
// <script src="callback_bender/lib/cb.iife.js"></script> you should use callback_bender.efc.none etc
// .ts file and .mjs file are also in the lib folder

Let's say we have a function as follows:

function ugly(efc) {
      // some code that will at some point call your callback with error or result
    };

Normally we would use this function as follows:

ugly((err, res)=>{ 
    if(err){ 
    handleError(err);
    } else{
    doSomething(res);
    }
 });

The callback is an error first callback, and takes one other argument. so we should use .efc.single() or .node.single():

// async/await style
try{
const res = await bend.efc.single(ugly)();
doSomething(res);
}catch(err){
handleError(err);
}

// promise style
bend.efc.single(ugly)().then(res => { doSomething(res); }).catch(err => { handleError(err); };

Let's see an example of none and CP, the API function would probably be something like:

function ugly(a, b, c, cp) => {
 // please note that a, b, c are not what we count as argument counts
      // this function calls cb() with no arguments or throws an error
    };

Normally we would use this function as follows:

ugly(()=>{ doSomething(); });

The callback is a normal callback, or CP, ( you can note that there is no error checking in callback ), and takes zero arguments. so we should use .cp.none() or .normal.none():

// async/await style
try{
await (bend.cp.none(ugly)(a,b,c,d));
doSomething();
}catch(err){ // the function might throw, so it's better to check
handleError(err);
}

// promise style
bend.cp.none(ugly)(a,b,c,d).then(() => { doSomething(); }).catch(err => { handleError(err); };

Let's see an example of multiple and efc, the API function would probably be something like:

function ugly(..., efc) {
 // function takes a callback
      // at some point the function will either call efc(err) or efc(undefined, res1, res2) so this callback will get more than one results
    };

Normally we would use this function as follows:

ugly((err, res1, res2)=>{ 
    if(err){ 
    handleError(err);
    } else{
    doSomething(res1);
    doStuff(res2);
    }
 });

The callback is an error first callback, and takes more than one argument (error doesn't count). so we should use .efc.multiple() or .node.multiple():

// async/await style
try{
const obj = await bend.efc.multiple(ugly)();
doSomething(obj[1]); 
doStuff(obj[2]);
}catch(err){
handleError(err);
}

// promise style
bend.efc.multiple(ugly)().then(obj => { doSomething(obj[1]); doStuff(obj[2]); }).catch(err => { handleError(err); };

Naming the .multiple object:

In the previous example, we can name the parameters on the object, by supplying an optional string array:

// async/await style
try{
const obj = await bend.efc.multiple(ugly,['first','second'])();
doSomething(obj.first); 
doStuff(obj.second);
}catch(err){
handleError(err);
}

// promise style
bend.efc.multiple(ugly,['first','second'])().then(obj => { doSomething(obj.first); doStuff(obj.second); }).catch(err => { handleError(err); };

A NodeJS fs example:

fs.readdir(path.join(...), (err, files) => {
            if(err){
            ...
            }else{
            ...
            }
          });

We are using an EFC (usual for node), and we are getting one argument (files) so:

const wrapped = bend.efc.single(fs.readdir);
wrapped(path.join(...)).then(res => ... ).catch(err => ... );

License

Distributed under the MIT License. See LICENSE for more information.

Contact

Antonio Ramirez: [email protected]

Project Link: Github