如果我有未知数量的请求,如何使用 jQuery.when().done() 实现 Promise.all().then() 行为?

How can I achieve Promise.all().then() behavior with jQuery.when().done() if I have an unknown number of requests?

我有这样一段代码:

var requestArray = [];
thingArray.forEach(function (thing) {
    var uri = "https://server/_api/endpoint/things(" + thing.Id + ")";
    requestArray.push($.ajax({
        url: uri,
        method: 'GET',
        headers: {
            accept: 'application/json;odata=verbose'
        }
    }));
});
$.when(requestArray).done(function(responseArray) {
    responseArray.forEach(function(response) {
        // response.responseJSON is undefined
    });
});

我意识到我遇到了时间问题并且 responseJSON 未定义,因为我正在将延迟的 数组 传递给 $.when(),期待它就像 Promise.all() (确实需要一个数组),但是 $.when() 只需要一个非结构化的 "group" 的 Deferreds,所以在我的例子中 $.when().done() 正在立即解析,因为传入数组对象

我试图通过

来绕过它
$.when(requestArray.forEach(function(req){ return req; })).done(function(responseArray) { })

(不能像 ...requestArray 那样解构,因为 IE 11),但在那种情况下 responseArray 最终成为 undefined

回顾 documentation for $.when(),我发现所有示例都有已知数量的请求,因此可以使用已知数量的参数设置 done 函数,例如

$.when(req1, req2).done(function(resp1, resp2) { // etc })

那么,如果我有未知数量的请求,我该如何设置 $.when().done() 才能工作?上例中我的 thingArray 是先前查询的结果,可以有任意数量的元素。

您可以使用 Function.apply() to invoke a function with an array as a list of parameters. To get the responses, iterate the arguments 数组,如对象:

$.when.apply($, requestArray).done(function() {
    for(var i = 0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
});

演示

var d1 = $.Deferred();
var d2 = $.Deferred();
var promiseArray = [d1.promise(), d2.promise()];

$.when.apply($, promiseArray).done(function() {
  for(var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
});

d1.resolve("Fish");
d2.resolve("Pizza");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>