Files
Zos/Skills/@be/node_modules/deferential/README.md

188 lines
5.5 KiB
Markdown

# deferential
es6 Native Promise Defer that helps build promise/callback dual APIS
[![build status](https://secure.travis-ci.org/eugeneware/deferential.png)](http://travis-ci.org/eugeneware/deferential)
## Installation
This module is installed via npm:
``` bash
$ 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](https://github.com/kriskowal/q/wiki/API-Reference#deferredmakenoderesolver)
and [bluebird](http://bluebirdjs.com/docs/api/ascallback.html) 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](https://github.com/getify/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:
``` js
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:
``` js
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!
``` js
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:
``` js
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:
``` js
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](https://github.com/getify/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.