数组中,console.log可以显示其内容,但长度为0

Array in d3.js, console.log can show its contents, but its length is 0

本文关键字:显示 console log 数组      更新时间:2023-09-26

社区。我遇到了一个非常奇怪的d3.js行为。

在下面的html代码中,console.log打印出数组";项目";以及它在我的firefox控制台中的长度。奇怪的是,内容(A,B,C(在那里,但长度部分是0!!

感谢您的帮助!!

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
                                    
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>(function() {

var event = d3.dispatch("data");
var projects = [];

d3.tsv("example.tsv", type, function(input) {
  event.data(input);
  input.forEach(function (d) {
      if (projects.indexOf(d.project) == -1) {
        projects.push(d.project);
      }
  })
});

graph(event);

function graph(event) {
  event.on("data.graph", function(input) {
    console.log(projects, projects.length);
  });
}

function type(d, i) {
  d.id = i;
  d.project = d.project;
  return d;
}

})()</script>

以下是示例.tsv

project
A
B
C

编辑

好的,非常感谢拉尔斯。我在谷歌上搜索了d3.tsv和async,在奥里找到了一个页面:

http://chimera.labs.oreilly.com/books/1230000000345/ch05.html#_data

请注意,d3.csv((是一个异步方法,这意味着即使JavaScript同时等待文件完成下载到浏览器,您的其余代码也会执行。(D3的其他加载外部资源的函数也是如此,比如D3.json((。(

这可能会非常令人困惑,因为作为一个理性的人,你可能会假设CSV文件的数据是可用的,而实际上它还没有完成加载。一个常见的错误是在回调函数之外包含对外部数据的引用。省去一些麻烦,并确保仅从回调函数中引用数据(或从回调函数内调用的其他函数中引用(。

就我个人而言,我喜欢先声明一个全局变量,然后调用d3.csv((来加载数据。在回调函数中,我将数据复制到我的全局变量中(这样它对我的所有后续函数都可用(,最后我调用任何依赖于该数据的函数。

我承认,这与我个人对程序范式的理解相矛盾。但console.log仍然让我感到困惑。正如Lars所说,console.log不是异步的,但它以另一种顺序评估这两个变量??这不是异步的定义吗??

这是因为d3.csv异步调用。也就是说,d3.csv块之后的代码可以在调用返回且数据可用之前运行。这就是Chrome中的情况,而Firefox加载数据的速度更快(可能是因为缓存?(。

处理异步调用中检索到的数据的正确方法是完全在回调函数中,即

d3.tsv("example.tsv", type, function(input) {
  event.data(input);
  input.forEach(function (d) {
      if (projects.indexOf(d.project) == -1) {
        projects.push(d.project);
      }
  });
  graph(event);
});