Promises are meant to be chained

How is the use of javascript promises supposed to be different from the use of mere callback functions?

Promises (promise objects) are sometimes called “thenables” because one of their primary characteristics is possessing a then() method.

promise.then(…)

The then() method accepts (at least) two arguments: a success callback and a reject callback.

promise.then(success_callback, reject_callback)

One could use a promise in this way, i.e. pass then() two callbacks. However, promises are specially designed for a more elegant structure, where you pass only one callback at a time:

promise.then(success_callback)
.catch(reject_callback)

The then() method is not just a method of promises, but it also returns a promise. This makes chaining possible.

promise.then(…).then(…).then(…)

The method catch(callback) is just a synonym for then(null, callback).

promise.then(success_callback)
.then(null, reject_callback)

The advantage of the then/catch chain format becomes apparent when we have several asynchronous tasks to perform one after the other. Compare

promise_1.then(
 function() {
   promise_2.then(
     function() {
       promise_3.then(
         success_callback_3,
         reject_callback_3),
      reject_callback_2),
   reject_callback_1)

with

promise_1
 .then(success_callback_1)
 .then(promise_2)
 .then(success_callback_2)
 .then(promise_3)
 .then(success_callback_3)
 .catch(reject_callback)

The behavior will be the same. But the second version is more readable, more scalable, more maintainable.
The asynchronous chained promises pattern is similar to the synchronous try/catch pattern.

try {
 command_1
 command_2
 command_3
} catch (exception) {
 reject_action
}

Following is a short working example. Compare the two files promises_chained.js and promises_unchained.js. Functionally they are the same. Which one is more maintainable?


 

Leave a Reply