hybridables/hybridify

View on GitHub
.verb.md

Summary

Maintainability
Test Coverage
# [{%= name %}][author-www-url] [![npmjs.com][npmjs-img]][npmjs-url] [![The MIT License][license-img]][license-url] [![npm downloads][downloads-img]][downloads-url] 

> {%= description %}

[![code climate][codeclimate-img]][codeclimate-url] [![standard code style][standard-img]][standard-url] [![travis build status][travis-img]][travis-url] [![coverage status][coveralls-img]][coveralls-url] [![dependency status][david-img]][david-url]

You might also be interested in [letta][], [relike][], [relike-all][], [hybridify-all][].

## Wait, what?
Hybrids?! Yea, hybrids are just promises on steroids. The philosophy of hybrids are some edge use cases like when you want to use both promise-style api and callback-style api in same time.

Hybrids are perfect for these times of transition from old school callback hell to the new and modern, next-generation javascript world - Promises, Generators, Async Functions and Arrow functions.

If you have callback api, or even some synchronous libs, hybrids comes to the rescue - use hybridify and you are here - in Promises Land, with centralized error handling and no breaking changes.

You can use hybridify when you considered to deprecate the callback api and want to support it for next few versions. And all that, without breaking changes - users of your library or project will be able to decide what to use - promises or good old callbacks.

## Highlights
> A few features and main points.

- "promisify" synchronous and asynchronous functions
- no breaking changes between switching APIs - from callbacks to promises
- thin wrapper around [relike][] to add support for both promise and callback-style API
- only using [bluebird][], if not other Promise constructor provided through `.Promise` property
- [bluebird][] or the custom constructor is used only on environments that don't have support for native Promise
- works on any nodejs version - from `v0.10.x` to latest `v6+` [Node.js](https://nodejs.org)
- accept and works with javascript internal functions like `JSON.stringify` and `JSON.parse`

## Install
```
npm i {%= name %} --save
```

## Usage
> For more use-cases see the [tests](./test.js)

```js
const {%= varname %} = require('{%= name %}')
```

{%= apidocs('index.js') %}

### .Promise

While `{%= varname %}` always trying to use native Promise if available in the environment, you can
give a Promise constructor to be used on environment where there's no support - for example, old
broswers or node's 0.10 version. By default, `{%= varname %}` will use and include [bluebird][] on old environments,
as it is the fastest implementation of Promises. So, you are able to give Promise constructor, but
it won't be used in modern environments - it always will use native Promise, you can't trick that. You
can't give custom promise implementation to be used in any environment.

**Example**

```js
const fs = require('fs')
const {%= varname %} = require('{%= varname %}')

{%= varname %}.hybridify.Promise = require('q') // using `Q` promise on node 0.10
const readFile = {%= varname %}.hybridify(fs.readFile)

readFile('package.json', 'utf8', (err, val) => {
  if (err) console.error(err)
  console.log(val)
})
.then(console.log, err => {
  console.error(err.stack)
})
```

One way to pass a custom Promise constructor is as shown above. But the other way is passing it to `.Promise` of the hybridified function, like that

```js
const fs = require('fs')
const {%= varname %} = require('{%= varname %}')
const statFile = {%= varname %}.hybridify(fs.stat)

statFile.Promise = require('when') // using `when` promise on node 0.10
statFile('package.json').then(console.log, console.error)
```

One more thing, is that you can access the used Promise and can detect what promise is used. It is easy, just as `promise.Promise` and you'll get it.
Or look for `promise.___bluebirdPromise` and `promise.___customPromise` properties. `.___bluebirdPromise` (yea, with three underscores in front) will be true if environment is old and you didn't provide promise constructor to `.Promise`.  
So, when you give constructor `.__customPromise` will be true and `.___bluebirdPromise` will be false.

```js
const fs = require('fs')
const {%= varname %} = require('{%= varname %}')

const promise = {%= varname %}(fs.readFile, 'package.json', 'utf8', (err, val) => {
  if (err) console.error(err)
  console.log(JSON.parse(val).name) // => '{%= varname %}'
})
promise.then(JSON.parse).then(val => {
  console.log(val.name) // => '{%= varname %}'
}, console.error)

console.log(promise.Promise) // => used Promise constructor
console.log(promise.___bluebirdPromise) // => `true` on old env, falsey otherwise
console.log(promise.___customPromise) // => `true` when pass `.Promise`, falsey otherwise
```

Or finally, you can pass Promise constructor as second argument to `.promisify`/`.hybridify` method. Like that

```js
const fs = require('fs')
const {%= varname %} = require('{%= varname %}')
const readFile = {%= varname %}.hybridify(fs.readFile, require('when'))

const promise = readFile('index.js')

console.log(promise.Promise) // => The `when` promise constructor, on old environments
console.log(promise.___customPromise) // => `true` on old environments
```

{% if (verb.related && verb.related.list && verb.related.list.length) { %}
## Related
{%= related(verb.related.list, {words: 12}) %}
{% } %}

## Contributing
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/{%= repository %}/issues/new).  
But before doing anything, please read the [CONTRIBUTING.md](./CONTRIBUTING.md) guidelines.

## [Charlike Make Reagent](http://j.mp/1stW47C) [![new message to charlike][new-message-img]][new-message-url] [![freenode #charlike][freenode-img]][freenode-url]

[![{%= author.username %}.tk][author-www-img]][author-www-url] [![keybase {%= author.username %}][keybase-img]][keybase-url] [![{%= author.username %} npm][author-npm-img]][author-npm-url] [![{%= author.username %} twitter][author-twitter-img]][author-twitter-url] [![{%= author.username %} github][author-github-img]][author-github-url]

{%= reflinks(verb.reflinks) %}

[npmjs-url]: https://www.npmjs.com/package/{%= name %}
[npmjs-img]: https://img.shields.io/npm/v/{%= name %}.svg?label={%= name %}

[license-url]: https://github.com/{%= repository %}/blob/master/LICENSE
[license-img]: https://img.shields.io/npm/l/{%= name %}.svg

[downloads-url]: https://www.npmjs.com/package/{%= name %}
[downloads-img]: https://img.shields.io/npm/dm/{%= name %}.svg


[codeclimate-url]: https://codeclimate.com/github/{%= repository %}
[codeclimate-img]: https://img.shields.io/codeclimate/github/{%= repository %}.svg

[travis-url]: https://travis-ci.org/{%= repository %}
[travis-img]: https://img.shields.io/travis/{%= repository %}/master.svg

[coveralls-url]: https://coveralls.io/r/{%= repository %}
[coveralls-img]: https://img.shields.io/coveralls/{%= repository %}.svg

[david-url]: https://david-dm.org/{%= repository %}
[david-img]: https://img.shields.io/david/{%= repository %}.svg

[standard-url]: https://github.com/feross/standard
[standard-img]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg


[author-www-url]: http://www.{%= author.username.toLowerCase() %}.tk
[author-www-img]: https://img.shields.io/badge/www-{%= author.username.toLowerCase() %}.tk-fe7d37.svg

[keybase-url]: https://keybase.io/{%= author.username.toLowerCase() %}
[keybase-img]: https://img.shields.io/badge/keybase-{%= author.username.toLowerCase() %}-8a7967.svg

[author-npm-url]: https://www.npmjs.com/~{%= author.username.toLowerCase() %}
[author-npm-img]: https://img.shields.io/badge/npm-~{%= author.username.toLowerCase() %}-cb3837.svg

[author-twitter-url]: https://twitter.com/{%= author.username %}
[author-twitter-img]: https://img.shields.io/badge/twitter-@{%= author.username %}-55acee.svg

[author-github-url]: https://github.com/{%= author.username %}
[author-github-img]: https://img.shields.io/badge/github-@{%= author.username %}-4183c4.svg

[freenode-url]: http://webchat.freenode.net/?channels=charlike
[freenode-img]: https://img.shields.io/badge/freenode-%23charlike-5654a4.svg

[new-message-url]: https://github.com/{%= author.username %}/ama
[new-message-img]: https://img.shields.io/badge/ask%20me-anything-green.svg