Awesome
hybridify
Hybridify. Hybrids. Create sync or async function to support both promise and callback-style APIs in same time. Using the power of relike.
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 latestv6+
Node.js - accept and works with javascript internal functions like
JSON.stringify
andJSON.parse
Install
npm i hybridify --save
Usage
For more use-cases see the tests
const hybridify = require('hybridify')
hybridify
Make sync or async
fn
to support promise and callback-style APIs in same time.
Params
<fn>
{Function}: Some sync or asynchronous function.[...args]
{Mixed}: Any number of any type of arguments, they are passed tofn
.returns
{Promise}: Always Promise, always native Promise if supported on environment.
Example
const fs = require('fs')
const hybridify = require('hybridify')
const promise = hybridify(fs.readFile, 'package.json', (err, buf) => {
if (err) console.error('callback err:', err)
console.log('callback res:', buf) // => '<Buffer 7b 0a 20 ...>'
})
promise.then(buf => {
console.log('promise res:', buf) // => '<Buffer 7b 0a 20 ...>'
}, err => {
console.error('promise err:', err.stack)
})
.hybridify
Wrapper function for
hybridify()
, but acts like.promisify
thingy. Acceptsfn
function and returns a function, which when is called returns a Promise, but also can accept and calls final callback if given.
Params
<fn>
{Function}: Some sync or asynchronous function.[Promize]
{Function}: Promise constructor to be used on environment where no support for native.returns
{Function}: Hybridified function, which always return a Promise.
Example
const fs = require('fs')
const hybridify = require('hybridify')
const readdir = hybridify.hybridify(fs.readdir)
const promise = readdir('./', (err, files) => {
if (err) console.error('callback err:', err)
console.log('callback res:', files) // => array with directory files
})
promise.then(files => {
console.log('promise res:', files) // => array of files
}, err => {
console.error('promise err:', err.stack)
})
.promisify
Alias for relike's
.promisify
method. Almost the same as the.hybridify
method, but can't accept callback. When returned function is called only returns a promise, not calls the final callback.
Params
<fn>
{Function}: Some sync or asynchronous function.[Promize]
{Function}: Promise constructor to be used on environment where no support for native.returns
{Function}: Promisified function, which always return a Promise.
Example
const fs = require('fs')
const hybridify = require('hybridify')
const statPromised = hybridify.promisify(fs.statSync)
statPromised('./index.js').then(stats => {
console.log(stats.mode) // => mode of file
}, err => {
console.error(err.stack)
})
.Promise
While hybridify
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, hybridify
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
const fs = require('fs')
const hybridify = require('hybridify')
hybridify.hybridify.Promise = require('q') // using `Q` promise on node 0.10
const readFile = hybridify.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
const fs = require('fs')
const hybridify = require('hybridify')
const statFile = hybridify.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.
const fs = require('fs')
const hybridify = require('hybridify')
const promise = hybridify(fs.readFile, 'package.json', 'utf8', (err, val) => {
if (err) console.error(err)
console.log(JSON.parse(val).name) // => 'hybridify'
})
promise.then(JSON.parse).then(val => {
console.log(val.name) // => 'hybridify'
}, 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
const fs = require('fs')
const hybridify = require('hybridify')
const readFile = hybridify.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
Related
- callback2stream: Transform sync, async or generator function to Stream. Correctly handle errors. homepage
- letta: Promisify sync, async or generator function, using relike. Kind of promisify, but… more | homepage
- limon: The pluggable JavaScript lexer. Limon = Lemon. | homepage
- promise2stream: Transform ES2015 Promise to Stream - specifically, Transform Stream using… more | homepage
- relike-all: Promisify all function in an object, using relike. | homepage
- relike-value: Create promise from sync, async, string, number, array and so on. Handle… more | homepage
- relike: Simple promisify async or sync function with sane defaults. Lower level than… more | homepage
- value2stream: Transform any value to stream. Create a stream from any value -… more | homepage
Contributing
Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.
But before doing anything, please read the CONTRIBUTING.md guidelines.