Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript jQuery延迟';s、 $.when()和fail()回调参数_Javascript_Jquery_Jquery Deferred - Fatal编程技术网

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");
          });
      });
  });