简体   繁体   English

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

[英]Using queue() to load multiple files and assign to globals

I cannot get multiple files to load data and assign to globals. 我无法获取多个文件来加载数据并分配给全局变量。 I've read up on similar questions and related examples , but I still am having trouble. 我已经阅读了类似的问题相关的例子 ,但我仍然遇到了麻烦。

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);
}

I'm happy to filter the geoJSON features within ready() if that works better, but I need it to happen before I start creating the map with 如果效果更好,我很乐意在ready()过滤geoJSON功能,但我需要在开始创建地图之前将其发生

d3.g.selectAll("path")
    .data(geoJSON.features)
  .enter.append("path")
...

I'm assuming this has to do with callbacks and empty results, but I can't quite get it working. 我假设这与回调和空结果有关,但我不能让它工作。 I have figured out that using .await(console.log(geoJSON)); 我已经发现使用.await(console.log(geoJSON)); outputs the correct object to the console. 将正确的对象输出到控制台。 The ready() function won't execute though. ready()函数不会执行。 Thanks for any help understanding and fixing this problem. 感谢您帮助理解并解决此问题。

Your question was already answered by Jason Davies' reply to the thread you linked but anyway, here it is re-stated in terms of your exact example... 你的问题已经由杰森戴维斯回复你所链接的主题回答了,但无论如何,这里根据你的确切例子重新陈述......

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);
}

I've never used queue but, if you think about it, it's pretty obvious from Jason's answer how it works. 我从来没有使用过队列,但如果你想一想,从杰森的回答中可以看出它是如何运作的。
The basic pattern is 基本模式是

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

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

The call signature for the first argument of .defer is function(url, callback) and signature of the callback is function(error, result) . .defer的第一个参数的调用签名是function(url, callback)签名是function(error, result) The former is aligned with d3 conventions (for which queue is obviously designed) and the later is asynchronous javascript (ie node) conventional practice. 前者与d3约定(显然设计了队列)对齐,后者是异步javascript(即节点)常规实践。
To make this work, under the hood, queue needs to provide the callback argument, and that needs to be a function that hits the await object, with the result of the asynch request as arguments, using the standard function(error, result) signature. 为了使这项工作在底层,队列需要提供回调参数,并且需要使用标准function(error, result)签名,使用asynch请求作为参数来命中await对象的function(error, result)

If you use the direct pattern, where the first argument of defer is d3.csv for example, then, after it completes, d3.csv will invoke the callback provided by queue, therefore connecting with the await object, passing it's error/result state. 如果你使用直接模式,例如defer的第一个参数是d3.csv ,那么,在完成之后, d3.csv将调用队列提供的回调,因此连接到await对象,传递它的错误/结果状态。

In the indirect pattern described by Jason Davies, d3.csv is wrapped in another function - with the same signature - that defers invocation of the internally provided queue callback, until after d3.csv has completed and your post-processing is done. 在Jason Davies描述的间接模式中, d3.csv被包装在另一个函数中 - 具有相同的签名 - 延迟内部提供的队列回调的调用,直到d3.csv完成并且你的后处理完成之后。

Now that we understand what's going on, we can think about refactoring to make it cleaner. 现在我们了解了正在发生的事情,我们可以考虑重构以使其更清洁。 Perhaps like this... 也许这样......

queue(1)
    .defer(d3.csv, "path_to.csv")
    .defer(d3.json, "path_to.json")
    .await(ready);

function ready(error, csvData, jsonData) {
    if(error) return console.log("error: " + error.responseText);
    csvData.forEach(function(d) {origins.push(d.o_geoid)})
    // 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]);
        }
    }
}

...which has exactly the same effect. ...具有完全相同的效果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM