javascript - 在 JQuery $.when 调用中处理可变数量的延迟请求的更好方法?

标签 javascript jquery json jquery-deferred .when

我正在编写一个应用程序,在某个时候需要在继续之前获得一些请求的结果。这似乎是使用 JQuery 的 when 的可能候选者。例如:

 // requests is an array of Deferreds
 $.when.apply(null, requests).done(function(results) {
     // process results
 }

要注意的是,请求的数量可能是 1 个,也可能更多,when 函数以不同方式处理这些情况。只有一个请求,回调获取标准 (data, textStatus, jqXHR) 参数,但是当提供多个请求时,回调接收一系列参数:每个请求的 (data, textStatus, jqXHR) 值数组。令人沮丧的是,JQuery 似乎将请求的单例数组视为与单个参数请求相同,这意味着必须以不同方式处理这种情况。

我能想出的最好的办法来梳理这些案例,感觉有点笨拙,并且由于不同案例中结果参数的微妙之处,我花了一段时间才弄清楚,然后是请求数组的菜鸟陷阱需要被包裹在一个函数中,以便可以在闭包中访问它。

$.when.apply(null, function (){return requests;}()).done(function(results) {
    if (requests.length == 1) {
        processResults(results);
    } else {
        for (var i=0; i < arguments.length; i++)
            processResults(arguments[i][0]);
    }
   moreStuff();
});

还有比这更好或更优雅的方式吗?

最佳答案

我看到这是一个较旧的问题,但最近我遇到了这个问题,我在搜索该问题时遇到了这个问题。我最终创建了自己的解决方案,所以我想我会在这里分享它作为答案。

简而言之,$.when() 的设计确实不适合用于动态数量的参数。事实上,动态论证有点糟糕。它既难用又行为不一致。

似乎 ES6 promise 规范的设计者同意,因为 Promise.all() 的模拟设计不同并且解决了这两个问题。所以,我能想到的处理 jQuery 的 $.when() 问题的最好办法是制作一个遵循 Promise.all() 规则的新版本因此使用起来更简单。 jQuery Ajax promise 返回一个包含三个值的数组,这些值以您提到的奇怪方式与 $.when() 交互,这让生活变得更加复杂。

因此,$.when() 有两个主要更改以生成 $.all():

  1. 让它接受一组 promise ,而不是单独的 promise 参数。这使您不必使用 .apply() 只是为了向 $.all() 发送可变数量的 promise 。

  2. 使 $.all() 的结果始终为数组形式,无论最初传入了多少 promise。这就是您在你的问题。幸运的是,不需要很多代码就可以解决这个问题。

可以这样做:

$.all = function (promises) {
    if (!Array.isArray(promises)) {
        throw new Error("$.all() must be passed an array of promises");
    }
    return $.when.apply($, promises).then(function () {
        // if single argument was expanded into multiple arguments, then put it back into an array
        // for consistency
        if (promises.length === 1 && arguments.length > 1) {
            // put arguments into an array
            return [Array.prototype.slice.call(arguments, 0)];
        } else {
            return Array.prototype.slice.call(arguments, 0);
        }
    })
};

你像$.when()一样使用它,除了你总是传递$.all()一个单一的参数,它是一个promises数组(不需要.apply() )并且它总是解析为一个结果数组的单个参数(更容易迭代 promise 结果的动态数字并且它总是一致的)。

因此,如果您有一个任意长度的 ajax promise 数组:

var promises = [url1, url2, url3].map(function(url) {
    return $.get(url);
});


$.all(promises).then(function(results) {
    // results are always consistent here no matter how many promises
    // were originally passed in, thus solving your original problem
    for (var i = 0; i < results.length; i++) {
        console.log(results[i]);
    }
});

关于javascript - 在 JQuery $.when 调用中处理可变数量的延迟请求的更好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20233478/

相关文章:

c# - ASP.NET 4.6 MVC 如何返回包含具有正确时区的日期时间数据的 Json 结果?

java - 当 JSON 键没有一个名称但值不同时,为 Jackson 设计 Java 类

javascript - 在angularjs中将base64图像数据转换为图像文件

php - 如何将值从 json_encode 传递到 angularjs

javascript - css 调整水平下拉菜单的大小

jquery - 尝试将 jQuery 插件包装为 Ember 组件

sql - Postgres JSON 数组带有连接?

javascript - POST 后保留表单值

javascript - 使用 Javascript 在标签中显示列表项

javascript - 如何发出改变 css 样式的事件