jQuery 延迟链失败继续
Continue of failure of jQuery Deferred chain
我正在 jQuery 中执行一系列顺序 AJAX 调用,使用通常的链接方法与 Deferred。第一次调用 returns 一个值列表,随后的调用是使用这些返回的列表条目进行的。在第一次调用 returns 列表后,后续调用可以按任何顺序进行,但必须一次进行一次。所以这就是我使用的:
$.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?似乎任何延迟的失败都会导致链的其余部分也失败。相反,我想记录错误并继续列表的其余部分。
使用 Promises/A+ 这就像
一样简单
promise.then(…, function(err) {
if (checkIfContinuable(err))
return valueToConinueWith;
else
throw new TerribleError(err);
})
不幸的是,jQuery is still not Promises/A+ compliant, and forwards the old value (result or error) - unless you return a jQuery Deferred from the callback. This works just the same way as rejecting from the success handler:
jDeferred.then(…, function(err) {
if (checkIfContinuable(err))
return $.Deferred().resolve(valueToConinueWith);
else
return $.Deferred().reject(new TerribleError(err));
})
从 jQuery 承诺链中的错误中恢复比使用 Promises/A+ 实现更冗长,后者自然会在 .catch 或 .then 的错误处理程序中捕获错误。您必须 throw/rethrow 才能传播错误状态。
jQuery 反过来。 .then 的错误处理程序(.catch 不存在)自然会传播错误状态。要效仿 "catch",您必须 return 一个已解决的承诺,链将沿着它的成功之路前进。
从您希望作为一系列异步调用基础的项目数组开始,使用 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.
我正在 jQuery 中执行一系列顺序 AJAX 调用,使用通常的链接方法与 Deferred。第一次调用 returns 一个值列表,随后的调用是使用这些返回的列表条目进行的。在第一次调用 returns 列表后,后续调用可以按任何顺序进行,但必须一次进行一次。所以这就是我使用的:
$.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?似乎任何延迟的失败都会导致链的其余部分也失败。相反,我想记录错误并继续列表的其余部分。
使用 Promises/A+ 这就像
一样简单promise.then(…, function(err) {
if (checkIfContinuable(err))
return valueToConinueWith;
else
throw new TerribleError(err);
})
不幸的是,jQuery is still not Promises/A+ compliant, and forwards the old value (result or error) - unless you return a jQuery Deferred from the callback. This works just the same way as rejecting from the success handler:
jDeferred.then(…, function(err) {
if (checkIfContinuable(err))
return $.Deferred().resolve(valueToConinueWith);
else
return $.Deferred().reject(new TerribleError(err));
})
从 jQuery 承诺链中的错误中恢复比使用 Promises/A+ 实现更冗长,后者自然会在 .catch 或 .then 的错误处理程序中捕获错误。您必须 throw/rethrow 才能传播错误状态。
jQuery 反过来。 .then 的错误处理程序(.catch 不存在)自然会传播错误状态。要效仿 "catch",您必须 return 一个已解决的承诺,链将沿着它的成功之路前进。
从您希望作为一系列异步调用基础的项目数组开始,使用 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.