Writing Clean Code With Nested Promises

javascript, node.js, promise

Solution

You can re-throw an error in the rejection handler to continue rejecting the promise, or you can return a new promise to replace the rejection.

exports.verify = function(data) {
  return postToService(data, "https://production-url.com")
    .fail(function(err) {
      if (err.code === 21007) {
        return postToService(data, "https://sandbox-url.com")
      } else {
        throw err
      }
    });
};

Problem

I'm writing an app that talks to Apple to verifyReceipts. They have both a sandbox and production url that you can post to. When communicating with Apple, if you receive a 21007 status, it means you were posting to the production url, when you should be posting to the sandbox one. So I wrote some code to facilitate the retry logic. Here's a simplified version of my code: ``` var request = require('request') , Q = require('q') ; var postToService = function(data, url) { var deferred = Q.defer(); var options = { data: data, url: url }; request.post(options, function(err, response, body) { if (err) { deferred.reject(err); } else if (hasErrors(response)) { deferred.reject(response); } else { deferred.resolve(body); } }); return deferred.promise; }; exports.verify = function(data) { var deferred = Q.defer(); postToService(data, "https://production-url.com") .then(function(body) { deferred.resolve(body); }) .fail(function(err) { if (err.code === 21007) { postToService(data, "https://sandbox-url.com") .then(function(body){ deferred.resolve(body); }) .fail(function(err) { deferred.reject(err); }); } else { deferred.reject(err); } }); return deferred.promise; }; ``` The retry portion in the verify function is pretty ugly and difficult to read with the nested promises. Is there a better way of doing this?

Original source