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

deferential

v1.0.0

Published

es6 Native Promise Defer that helps build promise/callback dual APIS

Downloads

106,486

Readme

deferential

es6 Native Promise Defer that helps build promise/callback dual APIS

build status

Installation

This module is installed via npm:

$ npm install deferential

Background

It is very easy to produce APIs that are equally consumable with node callbacks as well as promises.

Various promise libraries such as Q and bluebird have methods to either convert Promises or Deferred objects into forms that make it easy to adapt existing node.js APIS to support these DUAL APIs.

However, as of ES6 (and node 0.12), Promises are native in Javascript, and thus the need to have a heavy kitchen-sink API like Q or Bluebird is no longer necessary as we get fast native-only implementations of Promises.

And we can easily polyfill these with great libries such as native-promise-only.

Thus, we can create some small focused, modules to add these additional features that should work with any native Promise implementation.

Making a dual API function

Say you have a regular function tht returns the contents of a file.

Here is the callback version:

var fs = require('fs');

function getFile(fileName, cb) {
  fs.readFile(fileName, 'utf8', cb);
}

getFile('myfile.text', function (err, data) {
  if (err) return console.error(err);
  console.log(data);
});

Here is the promise version:

var Promise = require('native-promise-only'),
    fs = require('fs');

function getFile(fileName, cb) {
  var p = new Promise(function (resolve, reject) {
    fs.readFile(fileName, 'utf8', function (err, data) {
      if (err) return reject(err);
      resolve(data);
    });
  });
  return p;
}

getFile('myfile.txt')
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err);
  });

Here is a version that supports both!

var Promise = require('native-promise-only'),
    fs = require('fs'),
    Deferred = require('deferential');

function getFile(fileName, cb) {
  var d = Deferred();
  fs.readFile(fileName, 'utf8', d.resolver());
  return d.nodeify(cb);
}

// Use with callback
getFile('myfile.text', function (err, data) {
  if (err) return console.error(err);
  console.log(data);
});

// Use with promise
getFile('myfile.txt')
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err);
  });

The first line creats a new Deferred object:

var d = Deferred();

The d.resolver() returns a callback thunk which a standard node.js callback function can call, and then depending on the error state, it will resolve() or reject() the underlying promise (represented as d.promise).

The last line detects whether a cb callback arguments was passed in, and if it is, it will callback the supplied cb based on the success or failure of the underlying promise:

return d.nodeify(cb);

If the cb argument is missing (ie. undefined) then d.nodeify() returns the underlying promise so that the function can be used as a regular promise and chained with .then() and .catch() calls.

So, in summary, if a cb parameter is passed in d.nodeify() will call the callback as normal and all is good to use the function as a regular callback.

If the cb parameter is missing, then a promise is returned.

The Deferred object has resolve() and reject() methods on it to help resolve/reject the state of the underlying Promise. But there is also a helper method called Deferred#resolver() which returns a thunk that can easily passed into the callback paramter of regular node.js functions to automate the tedious if (err) return d.reject(err) logic.

API

Deferred()

Creates a new instance of a Deferred. It can be created with or without the new operator.

Deferred#resolve(value)

Resolve the underlying Promise.

Deferred#reject(err)

Reject the underlying Promise with an error.

Deferred#promise

Return the underlying Promise. NB: This is a Native Promise as the underlying library uses native-promise-only which will use the underlying Native Promise implementation or a native polyfill without all the guff.

Deferred#resolver()

Returns a node.js thunk (a function with the signature cb(err, results).

Pass this to a node.js style callback and then based on the result of the callback, the undelrying Promise will be resolved/rejected.

Deferred#nodeify(cb, [opts])

Call the provided cb node.js callback function if the underlying promise is resolved/rejected. If not, return the underlying promise to allow for regular Promise thenable chaining.

  • cb - node callback that will be called when the underlying Deferred#promise is resolved/rejected.
  • opts:
    • spread - (default: false). When true when multiple return arguments are provided by the #resolver(), they will be mapped to additional return arguments in the callback. This is because Promises can only return a single value, whereas node.js callbacks can return multiple return values (eg. cb(null, val1, val2). If this is false and multiple return values are returned, then the multiple values will be returned as a single array of the return values. See the tests for more details.