
Bluebird in the wild: Advanced promise-based workflows - sundip
http://blog.runnable.com/post/143035495456/bluebird-in-the-wild-advanced-promise-based
======
jwalton
If you're looking for a more lightweight solution than Bluebird (because, say,
you're writing client side code - Bluebird is a bit heavy weight):

* [promise-tools]([https://github.com/benbria/node-promise-tools](https://github.com/benbria/node-promise-tools)) is a library with a lot of the cool flow control from Bluebird, but is tiny and works with native Promises.

* [promise-breaker]([https://github.com/jwalton/node-promise-breaker](https://github.com/jwalton/node-promise-breaker)) is a library I wrote which is intended to make it really easy for third party libraries to support both promises and callbacks with a minimum of fuss (we also use this extensively internally as we convert our giant code base from callbacks to promises.) `callFn` and `applyFn` are also very handy for calling into existing callback based libraries from within promise based libraries.

~~~
untog
Ah, this was exactly what I was going to ask, thanks! Promise tools looks
great - do you know of any equivalents of promisify and promisifyAll? I use
them a lot with native libraries.

EDIT: to answer my own question, this looks like it'll do it:

[https://github.com/pgaubatz/node-es6-promisify-
all](https://github.com/pgaubatz/node-es6-promisify-all)

but it doesn't seem to be actively maintained.

~~~
mofle
Check out
[https://github.com/sindresorhus/pify](https://github.com/sindresorhus/pify)

------
tonyle
When I first got into promises, they were annoying for certain tasks.
Something as simple as download a list of 1000 files was hard to do since you
didn't want all the calls to fire off at once. After a long journey with
various techniques, I found out Bluebird map had a concurrency parameter.

return
Promise.map(arrayOfUrlsToDownload,downloadAndParseFunction,{concurrency:1})

One line for all your basic scraping/parsing needs.

~~~
DonPellegrino
There's also
[Bottleneck]([https://github.com/SGrondin/bottleneck](https://github.com/SGrondin/bottleneck))
for more fine grained concurrency.

------
danesparza
Quick question: With ES6/ES2015 based native promises on the way (see
[https://babeljs.io/docs/learn-es2015/](https://babeljs.io/docs/learn-es2015/)
), why would you still want to use something relatively proprietary like
Bluebird?

~~~
onestone
Because:

1) Bluebird is orders of magnitude faster and more memory-efficient than the
current V8 native promises. Better native promises performance has been
promised, but we are still waiting for it.

2) Bluebird is just as much standard-compliant as are the native promises.

3) Bluebird has very useful extensions, which are not (yet?) part of the
standard. You are not forced to use them, but they are still very nice to
have.

~~~
danesparza
Thanks! I appreciate the points.

------
joeyrobert
Good article but no mention of Promise.coroutine [1] which I find unfortunate.
It allows for a synchronous looking code using generators and yield. I've been
using it on express servers (in lieu of Koa) and it's worked great with
promise-based ORMs (BookshelfJS). Also allows for use of native try/catch.

[1]
[http://bluebirdjs.com/docs/api/promise.coroutine.html](http://bluebirdjs.com/docs/api/promise.coroutine.html)

~~~
farnsworth
Cool, like async/await in Typescript and which I think is coming in ES7.

------
diegorbaquero
Great article. I'm still using callbacks >.<

The _before_ code should not have Promise: "const fs =
Promise.promisifyAll(require('fs'))"

~~~
hiphipjorge
Thanks diego! Yes, you're totally right. That line is not needed. I'll go in
and fix it. But because of how `promisifyAll` works the code would still work
the same way :)

~~~
untog
One thing I was surprised to discover is that promisifyAll alters the original
object - which is actually great for ES6 imports. So:

    
    
       import fs from 'fs';
       Promise.promisifyAll(fs);
    

works great.

~~~
altano
That probably won't work when you switch from Babel=>ES5 to Babel=>ES6
([http://www.2ality.com/2015/07/es6-module-
exports.html?m=1](http://www.2ality.com/2015/07/es6-module-exports.html?m=1))
as ES6 bindings are immutable bindings to the actual values in the module
instead of copies.

------
karn09
Good read. I've been using bluebird in my own code lately and love it.

------
wrong_variable
Callbacks are fine, if you treat them as monads and only use them for
notification purposes.

In liveScript

do

    
    
      error,output <- fs.readFile "helloWorld.txt" 
      console.log output.toString() # => "hello world from txt file"
    

you can combine that with co-routines to create really powerful abstractions,
without the massive memory footprint of promises.

~~~
adrusi
Treating callbacks as monads is literally the definition of promises. If that
code does the same thing it did in 2011 when I last looked at livescript,
that's not treating callbacks as monads, thats just borrowing a syntax that
Haskell uses for monads and using it for callbacks.

