因此,在使用jQuery延迟和$.when
并行加载许多对象时。
$.when(
a.ajax(), b.ajax(), c.ajax()
).then(
//do something when all are complete
complete();
);
现在,b.ajax()
有时会失败,但我真的不在乎。我只想等到所有调用完成后再调用complete()。
不幸的是,只要b
失败,when()
就会拒绝,并且永远不会触发then()
回调。这是$.when()
的AFAIK期望行为,但在这种情况下非常适合我。
我实际上想要一种说法:
$.when(
a.ajax(), b.ajax().fail(return success), c.ajax()
).then(...)
或许有一种不同的方式可以使用when()
或更合适的构造?
答案 0 :(得分:6)
如果要捕获promise的失败并将其转换为成功,可以使用then的failFilter返回已解析的promise,如下所示:
deferredCall.then(function(answer) {
// this is success. you might transform the answer here.
return transformed;
}, function() {
// this is a fail. you might resolve the fail with an empty object.
return $.Deferred().resolve({}).promise();
});
这样做可以确保链条可以不间断地继续经过故障。
因此,对于您的示例,您可能会这样做:
$.when([
a.ajax(),
b.ajax().then(function(answer) {
return answer;
}, function() {
return $.Deferred().resolve({}).promise();
}),
c.ajax()
]).then(function(results) {
// etc.
});
示例2:在我的应用程序中,我有时使用then来获取特定实体的关系数据,并允许404表示不存在这种关系:
getEntity(id).then(function(entity) {
return getAssociation(id).then(function(association) {
entity.association = association;
return entity;
}, function() {
entity.association = null;
return $.Deferred().resolve(entity).promise();
});
}).done(function(entity) {
// etc.
});
注意,较旧的答案建议使用pipe方法。从jQuery 1.8开始,不推荐使用此方法。
答案 1 :(得分:3)
这不仅仅是将失败变成成功的事情。
鲜为人知的事实是,如果任何一个参数失败,$ .when()会立即执行then()回调。这是设计的。引用文档:
http://api.jquery.com/jQuery.when/
在多个Deferreds案例中,其中一个Deferreds被拒绝,jQuery.when立即触发其主Deferred的failCallbacks。请注意,此时某些延迟可能仍未解决。如果您需要为此情况执行其他处理,例如取消任何未完成的ajax请求,则可以在闭包中保留对基础jqXHR对象的引用,并在failCallback中检查/取消它们。
实际上没有内置的等待方式,直到所有这些方式都完成,无论其成功/失败状态如何。
所以,我为你建了一个$ .whenAll():)它总是等到所有这些都以某种方式解决:
答案 2 :(得分:1)
您可以通过包装$.onFailSucceed
对象来轻松构建$.Deferred
:
$.onCompleteSucceed = function(oldDfd) {
var newDfd = $.Deferred();
oldDfd.always(newDfd.resolve);
return newDfd.promise();
}
然后您可以在此方法中包装适当的调用:
$.when(
a.ajax(), $.onCompleteSucceed(b.ajax()), c.ajax()
).then(...)
答案 3 :(得分:1)