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?
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
}
});
};