Call a Node-style callback with the resolution value or rejection cause of a Promise without the common pitfalls.
npm install promise-nodeifypromise-nodeify
===============






Call a Node-style callback with the resolution value or rejection cause of a
Promise without the common pitfalls.
``js
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);
}
`
The important features of nodeify as compared to naive implementations:
* Creates Error for falsey rejection causes. Since Promises may resolve orError
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 when the rejection cause is falsey.cause
(and passing the original value as the property, as bluebird does).uncaughtException
* Exceptions thrown by callback cause as they would for.then
other callbacks (unlike passing callback to , which causesunhandledRejection
or swallows them).unhandledRejection
* 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 s and multiple threads of control - or returning.then
the result passing the callback to , which resolves to the callback
result).
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][bb-ascallback] | [es-nodeify][es-nodeify] | [nodeify][nodeify] | [then #nodeify][then-nodeify] | [Un-thenify][unthenify]1 | [when.js .bindCallback][when-bindcallback]function
--------------------------|-----------------------|----------------------------------------------|---------------------------------------|---------------------------------------|---------------------------------|------------------------------------------------|---------------------------------------------
returns (with ) | undefined | this Promise2 | undefined | Promise | undefined | undefined | when(promise)promise
returns (with falsey) | | promise | promise | Promise | promise | undefined with unhandledRejection | when(promise)promise
returns (non-function) | | promise | undefined with unhandledRejection | promise | promise | undefined with unhandledRejection | when(promise) with uncaughtExceptionuncaughtException
callback exception | | uncaughtException | unhandledRejection | uncaughtException | uncaughtException | unhandledRejection | uncaughtExceptionError
falsey cause | with .cause | Error with .cause3 | Error | falsey cause | falsey cause | TypeError | falsey causeundefined
reject argument length | 1 | 1 | 1 | 1 | 1 | 1 | 2
resolve argument length | 2 | ? 1 : 24 | 2 | 2 | 2 | 2 | 2this
extra argument | ignored | options5 | ignored | ignored | 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 toArray
pass values as separate arguments to callback.
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][npm-benchmark] | 2.1.0 |bluebird
| [][npm-bluebird] | 3.3.3 |cli-table
| [][npm-cli-table] | 0.3.1 |es-nodeify
| [][npm-es-nodeify] | 1.0.0 |microtime
| [][npm-microtime] | 2.0.0 |native-promise-only
| [][npm-native-promise-only] | 0.8.1 |nodeify
| [][npm-nodeify] | 1.0.0 |pinkie-promise
| [][npm-pinkie-promise] | 2.0.0 |promise
| [][npm-promise] | 7.1.1 |q
| [][npm-q] | 1.4.1 |rsvp
| [][npm-rsvp] | 3.2.1 |unthenify
| [][npm-unthenify] | 1.0.1 |when
| [][npm-when] | 3.7.7 |
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 |
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 |
This package can be installed
using npm by running:
`sh`
npm install promise-nodeify
This package can be installed using bower by running:
`sh`
bower install promise-nodeify
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:
`html`
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:
`js
// 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);
}
`
To polyfill the .nodeify (or .asCallback) method for a Promise library,.nodeifyThis
assign the function to Promise.prototype.nodeify as follows:
`js
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.
For a description of the available functions and their arguments, see the API
Documentation.
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.
This package is available under the terms of the
MIT License.
[bb-ascallback]: http://bluebirdjs.com/docs/api/ascallback.html
[es-nodeify]: https://github.com/robbertkl/es-nodeify
[nodeify]: https://github.com/then/nodeify
[npm-benchmark]: https://www.npmjs.com/package/benchmark
[npm-bluebird]: https://www.npmjs.com/package/bluebird
[npm-cli-table]: https://www.npmjs.com/package/cli-table
[npm-es-nodeify]: https://www.npmjs.com/package/es-nodeify
[npm-microtime]: https://www.npmjs.com/package/microtime
[npm-native-promise-only]: https://www.npmjs.com/package/native-promise-only
[npm-nodeify]: https://www.npmjs.com/package/nodeify
[npm-pinkie-promise]: https://www.npmjs.com/package/pinkie-promise
[npm-promise]: https://www.npmjs.com/package/promise
[npm-q]: https://www.npmjs.com/package/q
[npm-rsvp]: https://www.npmjs.com/package/rsvp
[npm-unthenify]: https://www.npmjs.com/package/unthenify
[npm-when]: https://www.npmjs.com/package/when
[then-nodeify]: https://github.com/then/promise#promisenodeifycallback
[unthenify]: https://github.com/blakeembrey/unthenify
[when-bindcallback]: https://github.com/cujojs/when/blob/master/docs/api.md#nodebindcallback