将一个Deferreds数组传递给$ .when()

这是正在发生的事情的一个虚构示例:http : //jsfiddle.net/adamjford/YNGcm/20/

HTML:

<a href="#">Click me!</a>
<div></div>

JavaScript:

function getSomeDeferredStuff() {
    var deferreds = [];

    var i = 1;
    for (i = 1; i <= 10; i++) {
        var count = i;

        deferreds.push(
        $.post('/echo/html/', {
            html: "<p>Task #" + count + " complete.",
            delay: count
        }).success(function(data) {
            $("div").append(data);
        }));
    }

    return deferreds;
}

$(function() {
    $("a").click(function() {
        var deferreds = getSomeDeferredStuff();

        $.when(deferreds).done(function() {
            $("div").append("<p>All done!</p>");
        });
    });
});

我要“全部完成!” 在所有延迟任务完成后$.when()出现,但似乎不知道如何处理一系列Deferred对象。“全做完了!” 首先发生是因为数组不是Deferred对象,所以jQuery继续进行并假设它已经完成。

我知道有人可以像这样将对象传递给函数,$.when(deferred1, deferred2, ..., deferredX)但是未知我要解决的实际问题中执行多少个Deferred对象。

小次郎2020/03/14 17:51:09

如果您使用的是angularJS或Q Promise库的某些变体,那么您可以使用.all()一种解决此确切问题的方法。

var savePromises = [];
angular.forEach(models, function(model){
  savePromises.push(
    model.saveToServer()
  )
});

$q.all(savePromises).then(
  function success(results){...},
  function failed(results){...}
);

查看完整的API:

https://github.com/kriskowal/q/wiki/API-Reference#promiseall

https://docs.angularjs.org/api/ng/service/$q

神奇小小2020/03/14 17:51:09

我想用$ .each提出另一个建议:

  1. 我们可以像这样声明ajax函数:

    function ajaxFn(someData) {
        this.someData = someData;
        var that = this;
        return function () {
            var promise = $.Deferred();
            $.ajax({
                method: "POST",
                url: "url",
                data: that.someData,
                success: function(data) {
                    promise.resolve(data);
                },
                error: function(data) {
                    promise.reject(data);
                }
            })
            return promise;
        }
    }
    
  2. 我们使用ajax创建要发送的函数数组的一部分代码:

    var arrayOfFn = [];
    for (var i = 0; i < someDataArray.length; i++) {
        var ajaxFnForArray = new ajaxFn(someDataArray[i]);
        arrayOfFn.push(ajaxFnForArray);
    }
    
  3. 并通过发送ajax调用函数:

    $.when(
        $.each(arrayOfFn, function(index, value) {
            value.call()
        })
    ).then(function() {
            alert("Cheer!");
        }
    )
    
JinJin乐2020/03/14 17:51:09

如果您正在转译并可以访问ES6,则可以使用传播语法,该语法专门将对象的每个可迭代项作为离散参数应用,恰恰是$.when()需要它的方式

$.when(...deferreds).done(() => {
    // do stuff
});

MDN链接-传播语法

小宇宙小小米亚2020/03/14 17:51:09

您可以将when方法应用于数组:

var arr = [ /* Deferred objects */ ];

$.when.apply($, arr);

您如何使用jQuery Deferreds数组?

Stafan卡卡西2020/03/14 17:51:09

要将值数组传递给通常希望它们是单独参数的任何函数,请使用Function.prototype.apply,因此在这种情况下,您需要:

$.when.apply($, my_array).then( ___ );

参见http://jsfiddle.net/YNGcm/21/

在ES6中,可以改为使用... 传播运算符

$.when(...my_array).then( ___ );

在这两种情况下,由于您不太可能事先知道.then处理程序需要多少个形式参数,因此该处理程序将需要处理arguments数组以检索每个Promise的结果。