1

我需要从服务器上的一系列 .csv 文件中提取数据。我正在将 csvs 转换为数组,并试图将它们全部保存在一个对象中。ajax 请求都是成功的,但由于某种原因,只有最后一个请求中的数据最终出现在对象中。这是我的代码:

var populate_chart_data = function(){
    "use strict";
    var genders = ["Boys","Girls"];
    var charts = {
        WHO: ["HCFA", "IWFA", "LFA", "WFA", "WFL"],
        CDC: ["BMIAGE", "HCA", "IWFA", "LFA", "SFA", "WFA", "WFL", "WFS"]
    };
    var fileName, fileString;
    var chart_data = {};
    for (var i=0; i < genders.length; i++){
        for (var item in charts){
            if (charts.hasOwnProperty(item)){
                for (var j=0; j<charts[item].length; j++) {
                    fileName = genders[i] + '_' + item + '_' + charts[item][j];
                    fileString = pathString + fileName + '.csv';
                    $.ajax(fileString, {
                        success: function(data) {
                            chart_data[fileName] = csvToArray(data);
                        },
                        error: function() {
                            console.log("Failed to retrieve csv");
                        },
                        timeout: 300000
                    });
                }
            }
        }
    }
    return chart_data;
};
var chart_data = populate_chart_data();

Firebug 中的控制台显示每个 ajax 请求都成功,但是当我单步执行循环时,我的 chart_data 对象在最后一个循环之前是空的。这是我第一次涉足ajax。是时间问题吗?

4

2 回答 2

2

这里有两件事你需要考虑:

  1. AJAX 调用是异步的,这意味着只有在收到数据后才会调用回调。同时,您的循环继续进行并将新请求排队。

  2. 由于您正在进行循环,因此filename您的回调执行之前的值将发生变化。

所以你需要做两件事:

  1. 将请求推送到数组中,仅在数组完成时返回
  2. 创建一个闭包,这样你的文件名就不会改变

.

var chart_data = [];
var requests = [];

for (var j=0; j<charts[item].length; j++) {
    fileName = genders[i] + '_' + item + '_' + charts[item][j];
    fileString = pathString + fileName + '.csv';
    var onSuccess = (function(filenameinclosure){               // closure for your filename
                        return function(data){
                            chart_data[filenameinclosure] = csvToArray(data);
                        };
                    })(fileName);
    requests.push(                                     // saving requests
        $.ajax(fileString, {
            success: onSuccess,
            error: function() {
                console.log("Failed to retrieve csv");
            },
            timeout: 300000
        })
    );
}

$.when.apply(undefined, requests).done(function () {
    // chart_data is filled up
});
于 2013-04-26T15:52:35.067 回答
1

我很惊讶任何数据最终都会出现在对象中。关于 ajax 的事情是你不能依赖于知道请求何时完成(或者它是否会完成)。因此,任何依赖于检索的工作都data必须在 ajax 回调中完成。你可以这样:

var requests = [];
var chart_data = {};
/* snip */
requests.push($.ajax(fileString, {
/* snip */

$.when.apply(undefined, requests).done(function () {
    //chart_data should be full
});
于 2013-04-26T15:43:03.230 回答