我在jQuery中进行了一系列连续的AJAX调用,使用了与Deferred链接的常用方法。第一个调用返回一个值列表,随后的调用将返回那些返回的列表条目。在第一次返回列表的调用之后,后续调用可以按任何顺序完成,但必须一次完成一次。所以这就是我使用的:
$.when(callWebService()).then(
function (data) {
var looper = $.Deferred().resolve(),
myList = JSON.parse(data);
for (var i in myList) {
(function (i) {
looper = looper.then(function () { // Success
return callWebService();
},
function (jqXHR, textStatus, errorThrown) { // Failure
if (checkIfContinuable(errorThrown) == true)
continueChain();
else
failWithTerribleError();
});
})(i);
}
});
事实证明,后续调用有时可能会失败,但我仍然希望进行剩余的调用。在我的列表中,这是一些创造性伪代码的意思:
if (checkIfContinuable(errorThrown) == true)
continueChain();
else
failWithTerribleError();
我实际上如何实现continueChain?似乎任何延迟的失败都会导致链的其余部分也失败。相反,我想记录错误并继续列表的其余部分。
答案 0 :(得分:5)
使用Promises/A+,这就像
一样简单promise.then(…, function(err) {
if (checkIfContinuable(err))
return valueToConinueWith;
else
throw new TerribleError(err);
})
不幸的是,jQuery is still not Promises/A+ compliant并转发旧值(结果或错误) - 除非您从回调中返回一个延迟的jQuery。这与rejecting from the success handler的工作原理相同:
jDeferred.then(…, function(err) {
if (checkIfContinuable(err))
return $.Deferred().resolve(valueToConinueWith);
else
return $.Deferred().reject(new TerribleError(err));
})
答案 1 :(得分:1)
从jQuery promise链中的错误中恢复比使用Promise / A +实现更加冗长,Promise / A +实现自然会捕获.catch或.then的错误处理程序中的错误。您必须抛出/重新抛出才能传播错误状态。
jQuery以相反的方式工作。一个.then的错误处理程序(.catch不存在)将自然地传播错误状态。要模仿" catch",您必须返回已解决的承诺,并且链将沿着其成功路径前进。
从您希望基于一系列异步调用的项目数组开始,使用Array.prototype.reduce()非常方便。
function getWebServiceResults() {
return callWebService().then(function(data) {
var myList;
// This is genuine Javascript try/catch, in case JSON.parse() throws.
try {
myList = JSON.parse(data);
}
catch (error) {
return $.Deferred().reject(error).promise();//must return a promise because that's what the caller expects, whatever happens.
}
//Now use `myList.reduce()` to build a promise chain from the array `myList` and the items it contains.
var promise = myList.reduce(function(promise, item) {
return promise.then(function(arr) {
return callWebService(item).then(function(result) {
arr.push(result);
return arr;
}, function(jqXHR, textStatus, errorThrown) {
if(checkIfContinuable(errorThrown)) {
return $.when(arr); // return a resolved jQuery promise to put promise chain back on the success path.
} else {
return new Error(textStatus);//Although the error state will be naturally propagated, it's generally better to pass on a single js Error object rather than the three-part jqXHR, textStatus, errorThrown set.
}
});
});
}, $.when([])) // starter promise for the reduction, resolved with an empty array
// At this point, `promise` is a promise of an array of results.
return promise.then(null, failWithTerribleError);
});
}
注意:
function getWebServiceResults() {...}
。callWebService()
被认为接受item
- 即myList
的每个元素的内容。checkIfContinuable()
必须至少接受一个参数。假设接受errorThrown
但可能同样接受jqXHR或textStatus。