Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/70.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.when-当所有延迟不再';未解决';(已解决或拒绝)?_Javascript_Jquery_Rest_Jquery Deferred - Fatal编程技术网

Javascript jQuery.when-当所有延迟不再';未解决';(已解决或拒绝)?

Javascript jQuery.when-当所有延迟不再';未解决';(已解决或拒绝)?,javascript,jquery,rest,jquery-deferred,Javascript,Jquery,Rest,Jquery Deferred,当多个延迟对象被传递到时,该方法从一个新的“主”延迟对象返回承诺,该对象跟踪已传递的所有延迟的聚合状态 该方法将 在所有延迟解决后尽快解决其主延迟,或 一旦其中一个延期被拒绝,立即拒绝延期的主控 如果主延迟已解析(即所有延迟已解析),则会将传递给jQuery.when的所有延迟的解析值传递给它。例如,当延迟是jQuery.ajax()请求时,参数将是请求的jqXHR对象,其顺序与参数列表中给出的顺序相同: $.when( $.getJSON('foo'), $.getJSON('bar') ).

当多个延迟对象被传递到时,该方法从一个新的“主”延迟对象返回承诺,该对象跟踪已传递的所有延迟的聚合状态

该方法将

  • 在所有延迟解决后尽快解决其主延迟,或
  • 一旦其中一个延期被拒绝,立即拒绝延期的主控
  • 如果主延迟已解析(即所有延迟已解析),则会将传递给jQuery.when的所有延迟的解析值传递给它。例如,当延迟是jQuery.ajax()请求时,参数将是请求的jqXHR对象,其顺序与参数列表中给出的顺序相同:

    $.when( $.getJSON('foo'), $.getJSON('bar') ).done(function(foo, bar) {
    
        // foo & bar are jqXHR objects for the requests
    
    });
    
    在多次延迟的情况下,其中一个延迟被拒绝,jQuery.when会立即为其主延迟发出失败回调,即使此时某些延迟可能仍未解决:

    $.when( $.getJSON('foo'), $.getJSON('bar') ).fail(function(req) {
    
        // req is the jqXHR object for one of the failed requests
    
    });
    

    当所有延迟传递给jQuery.when不再“未解决”(即所有延迟都是“已解决”或“已拒绝”)时,我需要启动回调。我可以发送带有200个OK代码的JSON对象(而不是发送带有404个Not Found错误状态代码的JSON),并在done()方法中确定成功/错误,但我更喜欢保持API RESTful。如何实现这一点?

    我认为最简单的方法是为每个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方法的承诺中,该方法用于已解决的承诺和已拒绝的承诺

    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(...)
    

    注意:
    d1.resolve本身就是一个回调函数,它不需要包装在
    函数(){…}
    block.

    @Alnitak answer很聪明,它帮助我清除了我创建的一个黑客程序,在这个程序中,我在某种程度上人为地解决了一个承诺——不管潜在的结果如何——以便我可以使用“when”批量处理多个请求,并使用“done”继续处理,不管它们成功/失败

    我“回答”阿尔尼塔克的回答是希望为他的建议提供另一个用途,该建议支持任意数量的潜在承诺

    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($deferred),并将其推送到一个数组($deferreds),进行异步调用,根据需要添加done/fail,但始终包含一个“always”,用于解析该实体的$deferred。注意,“始终”接收延迟的解析函数,而不是其调用


    “when”将$deferreds数组转换为“when”和的参数列表,因为这组延迟保证可以解决(多亏了always),现在可以定义一个“done”,在所有异步调用完成后将调用它,而不管这些调用是否成功。

    这里是一个jQuery插件,我修改了
    $的实际核心代码。when()
    来使用您的语义。由于缺少更好的名称,它被称为
    $.myWhen()

    (函数($){
    $.myWhen=函数(从属/*,…,从属*/){
    var i=0,
    responseValues=Array.prototype.slice.call(参数),
    长度=响应值。长度,
    //未完成的下属数量
    剩余=长度!==1 | |(substance&&jQuery.isFunction(substance.promise))?长度:0,
    //主延迟。如果responseValue只包含一个延迟值,就使用它。
    递延=剩余===1?下级:jQuery.deferred(),
    //更新所有“解决”、“拒绝”和“进度”值的函数
    updateFunc=函数(i、上下文、值){
    返回函数(值){
    上下文[i]=这个;
    values[i]=arguments.length>1?Array.prototype.slice.call(arguments):值;
    如果(值===progressValues){
    deferred.notifyWith(上下文、值);
    }否则如果(!(-剩余)){
    延迟。解析(上下文、值);
    }
    };
    },
    进度价值观、进度上下文、响应文本;
    //将听众添加到延迟的下属;将其他人视为已解决
    如果(长度>1){
    progressValues=新数组(长度);
    ProgressContext=新数组(长度);
    responseContext=新数组(长度);
    对于(;i

    只需将此代码放在加载jQuery的位置之后,
    $.myWhen()
    函数将与
    $.when()
    一起提供。除了语义之外,其他一切都是100%完全相同的。

    我最近制作了一个插件,可能会有所帮助。我叫它
    $。当所有的

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

    $.whenAll-()

    示例用法:

    $.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
          }
        }
      )
    ;
    
    我的实施:

    插件代码:

    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]);
           });
    
    查看小提琴:

    对Leo Hernandez解决方案的改进,用于更一般的用例,而不仅仅是从服务器获取资源,例如可以在
    $.whenAll = function (deferreds) {
        var lastResolved = 0;
        var wrappedDeferreds = [];
    
        for (var i = 0; i < deferreds.length; i++) {
            wrappedDeferreds.push($.Deferred());
            if (deferreds[i] && deferreds[i].always) {
                deferreds[i].always(wrappedDeferreds[lastResolved++].resolve);
            } else {
                wrappedDeferreds[lastResolved++].resolve(deferreds[i]);
            }
        }
    
        return $.when.apply($, wrappedDeferreds).promise();
    };
    
    $.whenAll([1, $.Deferred().resolve("Good"), $.Deferred().reject("Bad")])
        .done(function (result1, result2, result3) {
            // result1 -> 1
            // result2 -> "Good"
            // result3 -> "Bad"
        });
    
    var entities;
    // ...
    var deferreds = entities.map(function() {
        var deferred = $.Deferred();
        asyncFunc(this).done(...).fail(...).always(deferred.resolve);
        return deferred;
    }
    // ...
    $.when.apply($, deferreds).done(...)
    
            $.when
            (
                $.getJSON(...).then(function (results)
                {
                    console.log('SUCCESS REQUEST 1 BY ITSELF', results);
                }),
                $.getJSON(...).then(function (results)
                {
                    console.log('SUCCESS REQUEST 2 BY ITSELF', results);
                })
            ).then
            (
                function (results1, results2)
                {
                    console.log('BOTH REQUESTS SUCCESSFUL...');
                    console.log('results1', results1);
                    console.log('results2', results2);
                },
                function (error1, error2)
                {
                    console.log('AT LEAST 1 REQUEST FAILED...');
                    console.log('error1', error1);
                    console.log('error2', error2);                  
                }
            );