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

promise-nodeify

v3.0.1

Published

Call a Node-style callback with the resolution value or rejection cause of a Promise without the common pitfalls.

Downloads

109,377

Readme

promise-nodeify

Build Status: Linux Build Status: Windows Coverage Dependency Status Supported Node Version Version on NPM

Call a Node-style callback with the resolution value or rejection cause of a Promise without the common pitfalls.

Introductory Example

var promiseNodeify = require('promise-nodeify');

// Function which returns a Promise
function returnsPromise() {
  return new Promise(function(resolve, reject) {
    resolve(42);
  });
}

// Function which takes an optional node-style callback
function takesCallback(callback) {
  var promise = returnsPromise();
  // if callback is not a function, promise is returned as-is
  // otherwise callback will be called when promise is resolved or rejected
  // promise will not cause unhandledRejection if callback is a function
  return promiseNodeify(promise, callback);
}

Features

The important features of nodeify as compared to naive implementations:

  • Creates Error for falsey rejection causes. Since Promises may resolve or reject without providing a value or cause, the callback would have no way to distinguish success from failure. This module ensures the error argument is always truthy, substituting an Error when the rejection cause is falsey (and passing the original value as the .cause property, as bluebird does).
  • Exceptions thrown by callback cause uncaughtException as they would for other callbacks (unlike passing callback to .then, which causes unhandledRejection or swallows them).
  • The callback handles the promise rejection, preventing unhandledRejection (unlike if the promise were ignored and callback invoked directly).
  • Reduces confusion by only returning a Promise when no callback is given (as opposed to returning the promise argument, which creates uncertainty about unhandledRejections and multiple threads of control - or returning the result passing the callback to .then, which resolves to the callback result).

Behavior Comparison

This module provides similar behavior to several popular promise libraries in a promise-library-agnostic way which only requires the ES6 promise functionality subset. However, these existing implementations differ in subtle ways. A brief comparison:

Behavior | this module | bluebird #asCallback | es-nodeify | nodeify | then #nodeify | Un-thenify1 | when.js .bindCallback --------------------------|-----------------------|----------------------------------------------|---------------------------------------|---------------------------------------|---------------------------------|------------------------------------------------|--------------------------------------------- returns (with function) | undefined | this Promise2 | undefined | Promise<undefined> | undefined | undefined | when(promise) returns (with falsey) | promise | promise | promise | Promise<undefined> | promise | undefined with unhandledRejection | when(promise) returns (non-function) | promise | promise | undefined with unhandledRejection | promise | promise | undefined with unhandledRejection | when(promise) with uncaughtException callback exception | uncaughtException | uncaughtException | unhandledRejection | uncaughtException | uncaughtException | unhandledRejection | uncaughtException falsey cause | Error with .cause | Error with .cause3 | Error | falsey cause | falsey cause | TypeError | falsey cause reject argument length | 1 | 1 | 1 | 1 | 1 | 1 | 2 resolve argument length | 2 | undefined ? 1 : 24 | 2 | 2 | 2 | 2 | 2 extra argument | ignored | options5 | ignored | ignored | this of callback | ignored | ignored

Notes:

  1. Un-thenify serves a similar purpose, but wraps the Promise-returning function rather than taking the Promise as an argument.
  2. Temporarily reverted in https://github.com/petkaantonov/bluebird/issues/151 and restored in https://github.com/petkaantonov/bluebird/issues/168
  3. In response to https://github.com/petkaantonov/bluebird/issues/434
  4. In response to https://github.com/petkaantonov/bluebird/issues/170
  5. Supports the spread boolean option to pass Array values as separate arguments to callback.

Performance Comparison

These benchmarks were done using the benchmark/index.js script on an Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz with Node v4.3.1 on Linux and the following module versions:

| Module | Version | |--------------------------------------------------|---------| | benchmark | 2.1.0 | | bluebird | 3.3.3 | | cli-table | 0.3.1 | | es-nodeify | 1.0.0 | | microtime | 2.0.0 | | native-promise-only | 0.8.1 | | nodeify | 1.0.0 | | pinkie-promise | 2.0.0 | | promise | 7.1.1 | | q | 1.4.1 | | rsvp | 3.2.1 | | unthenify | 1.0.1 | | when | 3.7.7 |

Nodeify Resolved Promise

Performance (in operations per second) of calling nodeify on a resolved promise (larger is better):

| ops/sec | bluebird | native | npo | pinkie | q | rsvp | then | when | |-------------------|--------------:|------------:|------------:|------------:|-----------:|--------------:|--------------:|--------------:| | bluebird#nodeify | 1,922,721.987 | TypeError | TypeError | TypeError | TypeError | TypeError | TypeError | TypeError | | es-nodeify | 1,345,702.588 | 506,103.345 | 510,887.217 | 534,013.961 | 68,915.816 | 1,974,250.737 | 2,096,468.119 | 1,756,177.934 | | nodeify | 147,481.019 | 251,414.264 | 251,535.145 | 253,880.998 | 58,504.098 | 1,355,812.482 | 1,102,467.756 | 1,160,226.624 | | promiseNodeify | 1,586,092.279 | 481,842.79 | 452,529.247 | 455,657.062 | 66,045.273 | 2,108,607.126 | 2,370,823.723 | 1,942,722.539 | | then#nodeify | 136,716.987 | 202,670.23 | 225,297.257 | 231,042.286 | 56,384.953 | 764,719.55 | 1,320,158.92 | 739,062.155 | | unthenify | 100,638.922 | 79,097.99 | 80,488.25 | 78,298.365 | 40,683.82 | 103,125.162 | 100,618.139 | 101,887.997 | | when.bindCallback | 823.326 | 856.669 | 842.975 | 834.864 | 748.669 | 847.556 | 850.316 | 839.995 |

Nodeify Rejected Promise

Performance (in operations per second) of calling nodeify on a rejected promise (larger is better):

| ops/sec | bluebird | native | npo | pinkie | q | rsvp | then | when | |-------------------|--------------:|------------:|------------:|------------:|-----------:|--------------:|--------------:|--------------:| | bluebird#nodeify | 1,889,496.469 | TypeError | TypeError | TypeError | TypeError | TypeError | TypeError | TypeError | | es-nodeify | 1,247,981.228 | 520,349.959 | 455,337.77 | 466,964.692 | 64,703.247 | 2,182,281.005 | 2,062,330.035 | 1,889,184.935 | | nodeify | 147,454.87 | 325,956.476 | 326,958.556 | 325,971.637 | 53,878.098 | 1,232,726.201 | 952,338.091 | 926,626.949 | | promiseNodeify | 1,170,756.604 | 465,186.326 | 478,343.59 | 489,024.094 | 62,905.801 | 2,097,277.371 | 1,928,682.943 | 1,497,451.328 | | then#nodeify | 131,588.987 | 241,627.02 | 246,557.24 | 245,427.553 | 49,655.492 | 684,232.864 | 1,178,175.996 | 634,041.464 | | unthenify | 96,359.916 | 82,291.679 | 82,507.055 | 83,324.584 | 38,842.741 | 96,432.332 | 97,113.05 | 99,892.099 | | when.bindCallback | 822.083 | 837.698 | 848.358 | 851.348 | 789.546 | 854.184 | 844.102 | 851.644 |

Installation

NPM

This package can be installed using npm by running:

npm install promise-nodeify

Browser

This package can be installed using bower by running:

bower install promise-nodeify

Without Package Manager

This module is also available with a UMD loader, both minified and un-minified, in the dist directory. They can be downloaded, self-hosted, or loaded from a CDN. To use the RawGit CDN, use the following (X)HTML:

<script src="https://cdn.rawgit.com/kevinoid/promise-nodeify/v0.1.0/dist/promise-nodeify.min.js"></script>

Recipes

Delegate to Promise.prototype.nodeify

If the behavior differences discussed in the Behavior Comparison section (and any future differences which may occur) are not significant to your use case and you are interested in taking advantage of the potential performance benefit of the implementation provided by the promise library, use the .delegated function:

// Using .delegated delegates to .nodeify on the promise argument when present
var promiseNodeify = require('promise-nodeify').delegated;

function returnsPromise() {
  return new Promise(function(resolve, reject) {
    resolve(42);
  });
}

function takesCallback(callback) {
  var promise = returnsPromise();
  return promiseNodeify(promise, callback);
}

Polyfill Promise.prototype.nodeify

To polyfill the .nodeify (or .asCallback) method for a Promise library, assign the .nodeifyThis function to Promise.prototype.nodeify as follows:

Promise.prototype.nodeify = require('promise-nodeify').nodeifyThis;

function returnsPromise() {
  return new Promise(function(resolve, reject) {
    resolve(42);
  });
}

function takesCallback(callback) {
  var promise = returnsPromise();
  return promise.nodeify(callback);
}

More examples can be found in the test specifications.

API Docs

For a description of the available functions and their arguments, see the API Documentation.

Contributing

Contributions are welcome and very much appreciated! Please add tests to cover any changes and ensure npm test passes.

The dist files are only updated for releases, so please don't include them in pull requests.

If the desired change is large, complex, backwards-incompatible, can have significantly differing implementations, or may not be in scope for this project, opening an issue before writing the code can avoid frustration and save a lot of time and effort.

License

This package is available under the terms of the MIT License.