社区。我遇到了一个非常奇怪的d3.js行为。
在下面的html代码中,console.log打印出数组" projects"和它在我的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>
以下是example.tsv
project
A
B
C
修改
好的,非常感谢Lars。我用Google搜索了d3.tsv和async,在O&#39; Reilly找到了一个页面:
http://chimera.labs.oreilly.com/books/1230000000345/ch05.html#_data
请注意,d3.csv()是一种异步方法,这意味着即使JavaScript同时等待文件下载到浏览器中,其余代码也会执行。 (D3的其他加载外部资源的函数也是如此,例如d3.json()。)
这可能会非常令人困惑,因为作为一个合理的人,你可能会认为CSV文件的数据是可用的,而事实上它还没有完成加载。常见的错误是在回调函数之外包含对外部数据的引用。避免一些麻烦,并确保仅从回调函数(或在回调函数中调用的其他函数中)引用您的数据。
就个人而言,我首先要声明一个全局变量,然后调用d3.csv()来加载数据。在回调函数中,我将数据复制到我的全局变量中(因此它可用于我的所有后续函数),最后我调用任何依赖于该数据的函数。
我承认,这与我个人对程序范式的理解相矛盾。但是console.log仍然让我感到困惑。正如Lars所说,console.log不是异步的,但它以另一种顺序摧毁了两个变量?不是async ??
的定义答案 0 :(得分:2)
这是因为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);
});