当前位置:  开发笔记 > 编程语言 > 正文

jQuery.when - 当所有延迟不再"未解决"(解决或拒绝)时回调?

如何解决《jQuery.when-当所有延迟不再"未解决"(解决或拒绝)时回调?》经验,为你挑选了4个好方法。

当多个Deferred对象传递给jQuery.when时,该方法从一个新的"master"Deferred对象返回Promise,该对象跟踪它已经传递的所有Deferred的聚合状态.

该方法将

    一旦所有Deferred解决,就解决它的主延期,或者

    拒绝其主人一旦被拒绝一个延期,就拒绝延期.

如果主Deferred被解析(即所有Deferreds解析),则传递给传递给jQuery.when的所有Deferred的已解析值.例如,当Deferreds是jQuery.ajax()请求时,参数将是请求的jqXHR对象,按照它们在参数列表中给出的顺序:

$.when( $.getJSON('foo'), $.getJSON('bar') ).done(function(foo, bar) {

    // foo & bar are jqXHR objects for the requests

});

在其中一个Deferreds被拒绝的多个Deferreds案例中,jQuery.when立即激活其主Deferred的失败回调,即使某些Deferreds在此时仍未解决:

$.when( $.getJSON('foo'), $.getJSON('bar') ).fail(function(req) {

    // req is the jqXHR object for one of the failed requests

});

当所有传递给jQuery的Deferreds都不再"未解决"时,我需要触发一个回调(即所有的"被解决"或"被拒绝").我可以使用200 OK代码发送JSON对象(而不是发送带有404 Not Found错误状态代码的JSON)并在done()方法中确定成功/错误,但我更喜欢保持我的API RESTful.我怎么能做到这一点?



1> Alnitak..:

我认为,要做到这一点最简单的方法就是保持辅助Deferred对象周围的每个AJAX请求,并确保一个总是解决:

var d1 = $.Deferred();
var d2 = $.Deferred();

var j1 = $.getJSON(...).complete(d1.resolve);
var j2 = $.getJSON(...).complete(d2.resolve);

$.when(j1, j2).done( only fires if j1 AND j2 are resolved );

$.when(d1, d2).done(function() {
     // will fire when j1 AND j2 are both resolved OR rejected
     // check j1.isResolved() and j2.isResolved() to find which failed
});

这是利用额外的AJAX .complete()方法,jQuery增加了对AJAX方法的承诺,这个方法被称为已解决和被拒绝的承诺.

NB:d1.resolve它本身就是一个回调函数,它不需要包含在一个function() { ... }块中.



2> DazWilkin..:

@Alnitak的回答很聪明,帮助我抹去了我创造的一个黑客,我在某种程度上人为地解决了一个承诺 - 无论其根本结果如何 - 以便我可以使用'when'批处理多个请求并使用'done'无论成功/失败,都要继续.

我正在"回答"Alnitak的回答,希望能为他的建议提供另一种用途,支持任意数量的潜在承诺.

var asyncFunc, entity, entities, $deferred, $deferreds;
// ...
foreach (entity in entities) {
    $deferred = $.Deferred();
    $deferreds.push($deferred);
    asyncFunc(entity).done(...).fail(...).always($deferred.resolve);
}
// ...
$.when.apply($, $deferreds).done(...)

这是伪JavaScript,但它应该传达这种方法.对于一些任意大小的实体集,为每个实体创建一个延迟($ deferred)并将其推送到一个数组($ deferreds),进行异步调用,根据需要添加done/fail但总是包含一个解决这个问题的'always'实体的延期.注意 ''always'接收延迟的解析函数而不是它的调用.

'when'将$ deferreds数组转换为'when'的参数列表,并且由于这组延迟被保证解决(感谢始终),现在可以定义一个将被调用的'done'无论这些是成功还是失败,异步调用都会完成.



3> fearphage..:

我最近制作了一个可能有用的插件.我叫它$.whenAll.

此扩展将所有成功和失败视为进度事件.在所有承诺完成后,如果没有错误,全球承诺将得到解决.否则全球承诺将被拒绝.

$ .whenAll - https://gist.github.com/4341799(测试)

样品用法:

$.whenAll($.getJSON('foo'), $.getJSON('bar'))
  .then(
    doneCallback
    ,failcallback
    // progress callback
    // the only problem is $.ajax.done/fail states call their callbacks 
    // with params in different locations (except for state)
    ,function(data, state, jqXhr) {
      if (state == 'success') {
        // do happy stuff
      }
      else { // error (fail)
        // `data` is actually the jqXhr object for failed requests
        // `jqXhr` is the text of the error "Not Found" in this example
      }
    }
  )
;


虽然这是非常古老的,但这非常好,非常需要.谢谢!干得好,我特别欣赏这些测试.

4> leojh..:

我的实施:

插件代码:

jQuery.whenAll = function (deferreds) {
        var lastResolved = 0;

        var wrappedDeferreds = [];

        for (var i = 0; i < deferreds.length; i++) {
            wrappedDeferreds.push(jQuery.Deferred());

            deferreds[i].always(function() {
                wrappedDeferreds[lastResolved++].resolve(arguments);
            });
        }

        return jQuery.when.apply(jQuery, wrappedDeferreds).promise();
    };

要使用它:

jQuery.whenAll([jQuery.get('/your-resource'), jQuery.get('/your-resource')])
   .done(
       function(result1, result2) {
           console.log(result1[1]);
           console.log(result2[1]);
       });

看看小提琴: http ://jsfiddle.net/LeoJH/VMQ3F/

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有