Javascript jQuery延迟';s、 $.when()和fail()回调参数
当使用Javascript jQuery延迟';s、 $.when()和fail()回调参数,javascript,jquery,jquery-deferred,Javascript,Jquery,Jquery Deferred,当使用$时,我得到一个意外的结果。当()某个延迟操作未成功时 以这个JavaScript为例,它创建了2个延迟。第一个成功,第二个失败 var f1 = function() { return $.Deferred(function(dfd) { dfd.resolve('123 from f1'); }).promise(); }; var f2 = function() { return $.Deferred(function(dfd) {
$时,我得到一个意外的结果。当()
某个延迟操作未成功时
以这个JavaScript为例,它创建了2个延迟。第一个成功,第二个失败
var f1 = function() {
return $.Deferred(function(dfd) {
dfd.resolve('123 from f1');
}).promise();
};
var f2 = function() {
return $.Deferred(function(dfd) {
dfd.reject('456 from f2');
}).promise();
};
$.when(f1(), f2())
.then(function(f1Val, f2Val) {
alert('success! f1, f2: ' + JSON.stringify([f1Val, f2Val]));
})
.fail(function(f1Val, f2Val) {
alert('fail! f1, f2: ' + JSON.stringify([f1Val, f2Val]));
});
自己运行它:
我得到失败!f1、f2:[“456自f2”,空]
问题在于,在.fail()
回调中,与f2()
拒绝一起传递的值被路由到第一个参数,我希望在那里得到f1值。这意味着我真的无法知道哪个延迟对象实际发布了reject()
,我也不知道故障数据实际上属于哪个操作
我本以为.fail()
会得到参数null,'456from f2'
,因为第一个延迟的没有失败。还是我在这里做得不对
如果不遵守回调中的参数顺序,我如何知道哪些延迟失败,哪些拒绝参数属于哪个失败延迟?在内部,“拒绝”和“失败”路径由两个完全不同的队列处理,因此它的工作方式与您期望的不一样
为了知道从“when()”组中失败的原始延迟调用,您可以让它们将自己与.reject()”调用一起作为对象文本或其他内容的一部分传递。$。when()
将在任何一个参数失败时立即执行失败的回调(第二个参数传递到然后()
)。这是设计的。要引用文档,请执行以下操作:
在多次延迟的情况下,其中一个延迟被拒绝,jQuery.when会立即为其主延迟启动故障回调。请注意,某些延期可能在此时仍未解决。如果需要对这种情况执行其他处理,例如取消任何未完成的ajax请求,可以在闭包中保留对底层jqXHR对象的引用,并在failCallback中检查/取消它们
实际上,没有一种内置的方法可以获取一个回调,它会一直等到所有回调都完成,而不管它们的成功/失败状态如何
因此,我为您构建了一个$.whenAll()
:)
它总是等待,直到所有问题以某种方式解决:
我也遇到过同样的问题,我通过使用.always回调和检查延迟对象数组来处理它。我有未知数量的ajax调用,因此我必须执行以下操作:
// array of ajax deletes
var deletes = [];
$checkboxes.each(function () {
deletes.push(deleteFile(this));
});
$.when.apply($, deletes)
.always(function () {
// unfortunately .fail shortcircuits and returns the first fail,
// so we have to loop the deferred objects and see what happened.
$.each(deletes, function () {
this.done(function () {
console.log("done");
}).fail(function () {
console.log("fail");
});
});
});
deleteFile方法返回一个承诺,该承诺包含.done或.fail回调
这允许您在所有延期完成后采取行动。在我的例子中,我将显示一个删除文件错误摘要
我只是尝试了一下,不幸的是,我不得不设置一个间隔计时器来检查它们是否都是在延迟对象上的$之后真正完成的。这似乎很奇怪,而且违反直觉
仍然在努力理解这些尊重 非常老的问题,但现在,要等到所有问题都解决了,您可以使用since$。ajax
处理标准承诺
从jQuery 1.5开始,$.ajax()返回的jqXHR对象实现Promise接口,为它们提供Promise的所有属性、方法和行为
因此,您可以使用
Promise.allSettled([$.ajax(),$.ajax()]))
。然后((res)=>{
如果(res[0]。状态==‘已完成’){
console.log(res[0].value)
//做点什么
}否则{
控制台。错误('res1不可用')
}
if(res[1]。状态==‘已完成’){
console.log(res[1].值)
//做点什么
}否则{
控制台。错误('res2不可用')
}
})
Hmm,不太清楚我会如何设计它,但我想我的结果是有意义的。@Mootoo jQuery自从这个问题被回答以来已经改变了很多。它现在使用标准的承诺语义。您说“将立即执行then()回调”,但您包含的引语说“立即触发故障回调”——那么是哪一个呢<代码>\-:
@hippietrail两者都有。然后()在“已解决”或“已拒绝”延迟时激发。这被分类为拒绝,因此它会激发。不,它不会激发然后回调。。它触发失败回调。(从技术上讲,这可能是传递给“then”的“第二次”回调,但无论如何,这与大多数阅读您答案的人认为是“成功”回调的“then”回调不同)。近5年后,这个答案仍然很有用!谢谢@无限循环我们这里有什么更新吗?或者仍然被认为是作为解决方案提供的最佳答案?如果任何延迟失败,也总是会“短路”。除了IE 11不支持allsolited
@IanKemp有趣之外,我不知道,无论如何,我不需要IE,但这是一个好的观点。
// array of ajax deletes
var deletes = [];
$checkboxes.each(function () {
deletes.push(deleteFile(this));
});
$.when.apply($, deletes)
.always(function () {
// unfortunately .fail shortcircuits and returns the first fail,
// so we have to loop the deferred objects and see what happened.
$.each(deletes, function () {
this.done(function () {
console.log("done");
}).fail(function () {
console.log("fail");
});
});
});