我正在编写一个与Apple通话以验证收据的应用。他们有一个沙盒和生产网址,你可以发布到。
与Apple通信时,如果您收到21007状态,则表示您要发布到生产网址,当您应该发布到沙箱时。
所以我写了一些代码来促进重试逻辑。这是我的代码的简化版本:
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;
};
验证函数中的重试部分非常丑陋,难以使用嵌套的promise进行读取。有没有更好的方法呢?
答案 0 :(得分:5)
您可以在拒绝处理程序中重新抛出错误以继续拒绝承诺,或者您可以返回新承诺来替换拒绝。
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
}
});
};
答案 1 :(得分:1)
这里有几种可能性。因为这个问题具有个人品味的元素,你可能会也可能不喜欢你所看到的!
(录取 - 我尚未测试此代码)
选项1 - 使用resolve
和reject
的包装器。这会以辅助函数的形式增加“噪音”,但整理其余部分。
var resolve = function (deferred, ob) {
return function () {
deferred.resolve(ob);
};
};
var reject = function (deferred, ob) {
return function () {
deferred.reject(ob);
};
};
exports.verify = function(data) {
var deferred = Q.defer();
postToService(data, "https://production-url.com")
.then(resolve(deferred, body))
.fail(function(err) {
if (err.code === 21007) {
postToService(data, "https://sandbox-url.com")
.then(resolve(deferred, body))
.fail(reject(deferred, err));
} else {
deferred.reject(err);
}
});
return deferred.promise;
};
选项2 - 使用bind。这具有使用现有JS功能的优点,但在创建回调时您有deferred
的重复引用。
exports.verify = function(data) {
var deferred = Q.defer();
postToService(data, "https://production-url.com")
.then(deferred.resolve.bind(deferred, body))
.fail(function(err) {
if (err.code === 21007) {
postToService(data, "https://sandbox-url.com")
.then(deferred.resolve.bind(deferred, body))
.fail(deferred.reject.bind(deferred, err));
} else {
deferred.reject(err);
}
});
return deferred.promise;
};
选项3 - 使用bind和'方法句柄'(#2的微小变化)。
exports.verify = function(data) {
var deferred = Q.defer();
var resolve = deferred.resolve;
var reject = deferred.reject;
postToService(data, "https://production-url.com")
.then(resolve.bind(deferred, body))
.fail(function(err) {
if (err.code === 21007) {
postToService(data, "https://sandbox-url.com")
.then(resolve.bind(deferred, body))
.fail(reject.bind(deferred, err));
} else {
deferred.reject(err);
}
});
return deferred.promise;
};
选项4 - 延迟猴子补丁。
function patch(deferred) {
deferred.resolveFn = function (ob) {
return function () {
deferred.resolve(ob);
};
};
deferred.rejectFn = function (ob) {
return function () {
deferred.reject(ob);
};
};
return deferred;
}
exports.verify = function(data) {
var deferred = patch(Q.defer());
postToService(data, "https://production-url.com")
.then(deferred.resolveFn(body))
.fail(function(err) {
if (err.code === 21007) {
postToService(data, "https://sandbox-url.com")
.then(deferred.resolveFn(body))
.fail(deferred.rejectFn(err));
} else {
deferred.reject(err);
}
});
return deferred.promise;
};
答案 2 :(得分:0)
您可能会考虑以下内容。我认为明智地使用空格可以帮助提高可读性。您可能希望找到一个合理的风格标准,让您的团队感觉良好并坚持下去!
exports.verify = function(data) {
var deferred = Q.defer();
postToService(data, "https://production-url.com")
.then(deferred.resolve, function(err) {
if (err.code === 21007) {
postToService(data, "https://sandbox-url.com")
.then(deferred.resolve, deferred.reject);
} else { deferred.reject(err); }
});
return deferred.promise;
};
答案 3 :(得分:0)
var request = require('request')
, Q = require('q');
var PRODUCTION_URL = "https://production-url.com",
var SANDBOX_URL = "https://sandbox-url.com",
export.verify = function() {
return postToProduction(data)
.fail( function(error) {
if (error.code === 21007 ) return postToSanbox(data);
throw error;
});
}
function postToProduction(data) {
return postToService(data, PRODUCTION_URL);
}
function postToSandbox(data) {
return postToService(data, SANDBOX_URL);
}
function postToService(data, url) {
var deferred = Q.defer();
var options = {
data: data,
url: url
};
request.post(options, function(err, response, body) {
if (err) return deferred.reject(err);
if (hasErrors(response)) return deferred.reject(response);
deferred.resolve(body);
});
return deferred.promise;
}