I’m always on a look out for interesting modules and unusual solutions. When working with promises in Node.js, there’s a constant friction between callbacks that is Node’s defacto interface and your desire to use promises throughout your entire project. The now famous Bluebird (Github: petkaantonov/bluebird, License: MIT) library has a good collection of helper methods to assist you in going to and from callback world.
Over time I began to feel the need for a simple helper function to automagically integrate a callback style function into promises control flow. Calling promisify
each time on a function isn’t super fun and promisifyAll
feels a little odd to me and so yesterday I set out to look for a module that implements something like this:
1
2
3
|
Promise .call(fs.readFile, 'path/to/file.txt' , 'utf8' ) .then(console.log) |
Not surprisingly somebody else has already thought of this. I found the songbird module by Matt that implements a very clean interface for converting any callback style function to a return a promise instead. songbird does what is generally considered a no-no – it extends Object
and Function
prototype which gives you a magic promise
property on every function. songbird also wraps the Bluebird library so you don’t have to install both. Lets check it out:
1
|
npm install songbird |
Usage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var Promise = require( 'songbird' ); var fs = require( 'fs' ); // callback API fs.readFile( './package.json' , 'utf8' , function (err, pkg) { console.log( 'callbacks' , pkg); }); // songbird API fs.promise.readFile( './package.json' , 'utf8' ).then( function (pkg) { console.log( 'promise' , pkg); }); Promise .join( fs.promise.readFile( './package.json' , 'utf8' ), fs.promise.readFile( './songbird.js' , 'utf8' ) ) .spread( function (pkg, songbird) { console.log( 'package.json length is' , pkg.length); console.log( 'songbird.js length is' , songbird.length); }); |
Closing thoughts
While I think it’s a great idea to mix in the promise
property to Object
and Function
, however with great power comes great responsibility. I strongly urge against using songbird in modules that you would distribute on npm because it would have a very big side effect on anyone who dares to install your code. However, when used on a project that isn’t made available publicly, songbird would be a great asset.
Check out source code for this article on GitHub and an interactive example on Runnable. Let us know what you think! It’s not every day you encounter a module that boldly extends Object
and Function
.