使用$.when()和.then基于$.getJSON响应更新数组

Using $.when() and .then to update an array based on $.getJSON responses

本文关键字:getJSON 响应 数组 基于 更新 when 使用 then      更新时间:2023-09-26

我正在尝试使用来自多个getJSON请求的响应来更新数组值。我已经尝试了很多种方法,下面的片段是我使用过的最简单的形式。在.then()触发时,单个成功回调尚未更新数组,因此警报显示原始值。我还尝试将各个jqXHR对象存储在一个数组中并处理它们,但它们都是readyState:1。关于如何在回复全部完成后获得参考,有什么建议吗?

$(function() {
    var points = [['A', 12946],
                  ['B', 4223],
                  ['C', 2774],
                 ];
    function makePointCalls(i) {
        return $.getJSON("http://otter.topsy.com/searchcount.json?callback=?",
            {
                q: points[i][0]
            },
            function(data) {
                points[i][1] = data.response.d;
            }
        );
    }
    $.when($.each(points, function(i, value){
              makePointCalls(i);
            })
        ).then(function(){
            //alert me after all the getJSONs are done and array updated?
            alert(points);
        });
});//doc ready

您的代码需要对makePointCalls的返回值做出反应,该值在each循环中被丢弃。

未测试的代码片段如下(根据kas673的评论工作):

// Collect deferreds first
var deferreds = jQuery.map(points, function(i, value){
    return makePointCalls(i);
});
// Pass all deferreds to when
jQuery.when.apply(jQuery, deferreds).then(…);

请注意,使用map而不是each来创建具有makePointCalls的返回值(延迟)的数组。用于调用when的对apply的调用是为了确保when以文档格式接收其参数。如果将一个数组作为唯一参数传递给when,则可以假设它收到了一个已解析的延迟,并立即执行then中的函数。

关于应用程序的使用,一个更详细的解释是when假设所有内容都是已解析的延迟,而不是延迟。首先需要注意的是,递延是某种回调管理器。它保留成功/解析时调用的回调,以及失败/拒绝时调用的回叫。Deferred用于提供一个返回值,只有在以后才能知道函数调用是否成功。一个例子是您的AJAX请求,它需要等待服务器,但不应该阻止JavaScript的执行。

您对$.getJSON的每个调用都返回一个deferred,可用于对请求完成做出反应。$.when将任意数量的延迟作为其参数,并在已知延迟的聚合状态时(当when的所有参数都已解析或至少一个被拒绝时)立即调用then的参数。

deferreds作为Deferred对象的数组时,调用$.when(deferreds).then(callback)会导致立即调用callback,如前所述。当聚合状态已知时,调用$.when(deferred[0], deferred[1]).then(callback)确实调用callback。使用apply可以解压缩数组,并将数组中的每个元素用作调用apply的函数的参数(在您的情况下是when)。

再次检查您的ActiveX通知,因为Firebug在Firefox中运行,幸运的是ActiveX不受支持。任何与ActiveX相关的东西都可能是因为您使用的是Microsoft-only API,而您不应该这样做。

$.map(...).get()替换$.each(...),用return makePointCalls(i) 替换makePointCalls(i)

$(function() {
    var points = [['A', 12946],
                  ['B', 4223],
                  ['C', 2774],
                 ];
    function makePointCalls(i) {
        return $.getJSON("http://otter.topsy.com/searchcount.json?callback=?",
            {
                q: points[i][0]
            },
            function(data) {
                points[i][1] = data.response.d;
            }
        );
    }
    $.when($.map(points, function(i, value){
              return makePointCalls(i);
            }).get();
        ).then(function(){
            //alert me after all the getJSONs are done and array updated?
            alert(points);
        });
});//doc ready