HTML and CSS Reference
One of the biggest challenges of working exclusively with asynchronous interfaces
lies in deeply nested callbacks; any task that requires the result of asynchronous
calls to be processed in order must be nested to ensure ordered execution. Not only
is deeply nested code ugly and cumbersome to work with, it also presents a more
grave problem; nested calls cannot benefit from the possibility of parallel execution,
a bad trade-off to enable ordered processing.
We can untangle nested callbacks using promises . A promise is a representation
of an eventual value and it offers an elegant way of working with asynchronous code.
When an asynchronous method uses promises, it does not accept a callback, but
rather returns a promise, an object representing the eventual fulfillment of that call.
The returned object is observable, allowing calling code to subscribe to success and
error events on it.
When the original call that spawned the promise finishes, it calls the promise's
resolve method, which causes its success callback to fire. Similarly, in the event
that a call failed, the promise offers the reject method, which can be passed an
Using promises means that we don't have to nest callbacks unless we truly
depend on calls to occur in succession; thus, we gain more flexibility. For example,
we can issue a host of asynchronous calls and have them execute in parallel, but use
promises to group and process the results in any order we wish.
Node no longer comes with a promise API, but Kris Zyp has a nice imple-
mentation 4 that implements his proposal for a CommonJS Promise specification.
The version used in this topic is available from the topic's website. 5 Download it to
14.4.1 Refactoring addMessage to Use Promises
We will refactor the addMessage method to use promises. As we refactor, it is vital
that we run the tests between each step, and always keep them passing, to be sure we
didn't break anything. Changing the way a method works can be done by keeping
the old behavior until the new behavior is in place and all tests have been updated.
The fact that we can carry out a refactoring like this—changing fundamen-
tal behavior—without worrying about breaking the application, is one of the true
benefits of a good test suite.