This post has nothing to do with that argument.
building a library, you’re going to be supporting callbacks. It’s the reality
of the ecosystem. But there are certain problems for which some syntactic sugar is helpful.
Promises provide a wrapper for callbacks that
allow for a chainable API around a sequence of continuations. They’re not a native part of
the language, but there’s a strawman
for the inclusion of Promises in a future version of JS. In the meantime, you can use
the excellent Q Library from
jQuery includes its own Promises implementation (
$.ajax calls return Promises), but they’re slightly
divergent from the Q spec. You can read this excellent guide
explaining the differences between jQuery and Q promises, if you’re coming from one direction
or the other.
So much for introductions. I’ve been using promises for awhile now in some of my Node code, and there’s several cases where their inclusion can clean up an API. (One area: Mongo integration, where any simple action can require several callbacks.) One benefit of Promises is that they can provide exception isolation, just like continuation-passing. The Q wiki provides the following example:
1 2 3 4 5 6 7
In the above snippet, errors generated from the parser and the process function arne’t isolated. Promises, meanwhile, offer this exception isolation out of the box:
1 2 3 4 5 6 7 8
In the second example, the process function is only executed if
doesn’t throw an error. Conversely, this same goal could be achieved
1 2 3 4 5 6 7 8 9
One caveat is that when you’re chaining your promises together, the behavior is slightly different than you might expect:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
In the above example, if there is an error in
User.findOne, the error is
propagated throughout the chain, which means that your console will have both
error in findOne and
error in _hashPassword printed. There’s no way
of “breaking” from the promise chain early. But here’s the thing: you don’t have to.
Unless you’re interested in transforming error objects, there’s not much
point in catching promise errors in intermediary steps in the chain. So the
above code would be abbreviated:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
There’s simply no point to having
then failure handlers that just throw
an error, since the library throws and propagates errors for you automatically.
In promise chains, then, you have the benefit of isolating exceptions (only proceeding
from step to step if everything is ok) without the extra semantics of
if (err) return cb(err)
from continuation passing.