使用queue()加载多个文件并分配给全局变量

时间:2015-10-12 17:59:08

标签: javascript d3.js queue.js

我无法获取多个文件来加载数据并分配给全局变量。我已经阅读了similar questionsrelated examples,但我仍遇到问题。

var origins = [],
    geoJSON = {
      "type": "FeatureCollection",
      "features": []
    };

queue(1)
    .defer(d3.csv, "path_to.csv", function(d) {
        origins.push(d.o_geoid)
      })
    .defer(d3.json, "path_to.json", function(d) {
      // Limit GeoJSON features to those in CSV
      for (var i = d.features.length - 1; i >= 0; i--) {
        if($.inArray(d.features[i].properties['GEOID10'], origins) != -1) {
          geoJSON.features.push(d.features[i]);
        }
      }
    })
    .await(ready);

function ready() {
  console.log(geoJSON);
}

如果效果更好,我很乐意过滤ready()中的geoJSON功能,但我需要在开始使用

创建地图之前进行此操作
d3.g.selectAll("path")
    .data(geoJSON.features)
  .enter.append("path")
...

我认为这与回调和空结果有关,但我无法让它发挥作用。我已经发现使用.await(console.log(geoJSON));将正确的对象输出到控制台。但ready()函数不会执行。感谢您帮助理解并解决此问题。

1 个答案:

答案 0 :(得分:4)

Jason Davies' reply to the thread you linked已经回答了您的问题,但无论如何,此处已根据您的确切示例重新说明......

var origins = [],
    geoJSON = {
        "type": "FeatureCollection",
        "features": []
    };

queue(1)
    .defer(function(url, callback) {
        d3.csv(url, function(error, csvData) {
            if(!error) csvData.forEach(function(d) {origins.push(d.o_geoid)});
            callback(error, d);
        })
    }, "path_to.csv")
    .defer(function(url, callback) {
        d3.json(url, function(error, jsonData) {
            // Limit GeoJSON features to those in CSV
            for(var i = jsonData.features.length - 1; !error && i >= 0; i--) {
                if($.inArray(jsonData.features[i].properties['GEOID10'], origins) != -1) {
                    geoJSON.features.push(jsonData.features[i]);
                }
            }
            callback(error, jsonData);
        })
    }, "path_to.json")
    .await(ready);

function ready(error) {
    console.log(error ? "error: " + error.responseText : geoJSON);
}

我从来没有使用过队列,但是,如果你想一想,杰森的答案很明显,它是如何工作的。 基本模式是

queue()
    .defer(asynchRequest1, url1)
    .defer(asynchRequest2, url2)
    .await(callback)

function callback(error){
    console.log(error ? 
        "error: " + error.responseText : 
        "completed, " + (arguments.length - 1) + " objects retrieved"
    );
}  

.defer的第一个参数的调用签名是function(url, callback),回调的签名是function(error, result)。前者与d3约定(显然设计了队列)对齐,后者是异步javascript(即节点)常规实践。
为了使这项工作在底层,队列需要提供回调参数,并且需要使用标准{{1来命中await对象,并将asynch请求的结果作为参数。签名。

如果你使用直接模式,例如defer的第一个参数是function(error, result),那么,在完成之后,d3.csv将调用队列提供的回调,因此与{{{ 1}} object,传递它的错误/结果状态。

在Jason Davies描述的间接模式中,d3.csv被包含在另一个函数中 - 具有相同的签名 - 推迟内部提供的队列回调的调用,直到await完成后和你的帖子处理完成。

现在我们了解了正在发生的事情,我们可以考虑重构以使其更清洁。也许是这样......

d3.csv

......具有完全相同的效果。