30 comments

[ 2.8 ms ] story [ 92.2 ms ] thread
Great article. I'm still using callbacks >.<

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

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 :)
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.
There is nothing wrong in using callbacks. I actually see many developers over-use promises to the point where code is nearly unreadable.
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.
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.
> In liveScript

i.e. use a different language because callbacks in javascript suck ? I prefer promises thank you. And promises ARE monads. No need for liveScript.

Good read. I've been using bluebird in my own code lately and love it.
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) 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) 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.

Very neat! If you are interested in high level promises without any dependencies, like these, I have a small library inspired by some of the more useful helpers in Bluebird:

[extends-promise](https://github.com/kjvalencik/extends-promise)

Fair warning, it has an emphasis on simplicity of code rather than speed. It does a few things that are very likely inefficient. I wrote it primarily to scratch an itch I had--embedding in one-off node.js scripts without any dependencies.

I'm looking for an approach where promises can be canceled. For example, when I'm waiting for a promise p to be fulfilled, I might suddenly decide that I'm not interested anymore in the promise. So I could call (for example) p.cancel(), and the effect would be that the underlying code is stopped (and recursively everything it depends on).
Microsoft's RxJS does all that (and more): https://xgrommx.github.io/rx-book/content/getting_started_wi...

See this specific blog post for more details (though the Rx Book is fantastic): "That said, a sore point for Promises has always been their lack of cancelability. This leads to some interesting design patterns where you have to "protect" your promise callbacks from context-dependent changes. Because of this hoop-jumping, the most attractive RxJS feature that I've seen so far is the simple ability to cancel (aka, unsubscribe, aka, dispose) an RxJS stream before it completes."

http://www.bennadel.com/blog/3030-canceling-rxjs-observables... (Though there are RxJS interops with more than just Angular)

Promises, and in particular bluebird promises, are cancellable.
ECMAscript 6 has cancellable promises? This guy[1] seems to claim otherwise. I spent 20 minutes on skimming the spec[2] and from what I can tell, there's no language feature that has that `promiseCapability'[3] and those stackoverflow workarounds remain the only native ECMAscript way to do it.

(I had to look up what that bluebird was and it looks like they both are libraries that offer cancellable functionality that the callee can invoke. So it looks like one is left to libraries regardless of Bluebird or RxJS or another solution. I'd opt for RxJS personally as RxJS is fairly first-class in the MS ecosystem (maybe one half-step beneath F#), and a lot of the product is based off of the RX research done by de Smet, Meijers, Beckman, et al (they've thrown prime engineering talent at it for years working out the concurrency semantics). But again, not in the JS ecosystem and just skimmed the standard[4] revision so there's a very high chance of me being wrong. I try to limit my comments to topics on which I'm relatively well-informed in general; in this case, please do regard my comments as poorly-informed-at-best.)

[1] http://stackoverflow.com/a/30235261 [2] https://tc39.github.io/ecma262/ [3] https://tc39.github.io/ecma262/#sec-promise-executor [4] Oh god, 25.4.4.1.1 - Runtime Semantics: PerformPromiseAll( iteratorRecord, constructor, resultCapability ). And I thought 'Rails magic' was bad. Step 6 goes all the way down from [a..r] haha.

ECMAScript doesn't have cancellable promises, but then again it doesn't have observables or async iterators either.

Native observables are less capable in this regard than native promises since they're non existent yet.

Bluebird promises are cancellable.

For what it's worth I've discussed this personally with Meijer (it's Meijer, not Meijers) and he agrees that cancellable promises are not problematic one bit.

Promises, observables and other async primitives all co-exist just fine :)

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

Bluebird provides a lot of really useful methods and abstractions over promises that we use on a daily basis. Basically all the methods I point out in the article are not part of the Promise spec (and probably won't be). The other thing that Bluebird helps a lot with is providing functionality around transitioning from non-promise code to promises by providing methods such as `promisify`, `promisifyAll`, `fromCallback`, and `asCallback`.

Bluebird made a name for itself by really, really focusing on V8-specific optimizations. Also it has added a lot of features that go beyond the promise spec, thus becoming one of those bandwagony swiss army knife sort of libraries. I personally use it for how efficient it is in Node.
"proprietary" is an odd way to describe a MIT licensed project.
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.

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

Cool, like async/await in Typescript and which I think is coming in ES7.
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.