社区。我遇到了一个非常奇怪的 d3.js 行为。
在下面的 html 代码中,console.log 在我的 Firefox 控制台中打印出数组“projects”及其长度。奇怪的是,内容(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
编辑
好的,非常感谢 Lars。我用 google 搜索 d3.tsv 和 async,在 O'Reilly 中找到了一个页面:
http://chimera.labs.oreilly.com/books/1230000000345/ch05.html#_data
Note that d3.csv() is an asynchronous method, meaning that the rest of your code is executed even while JavaScript is simultaneously waiting for the file to finish downloading into the browser. (The same is true of D3’s other functions that load external resources, such as d3.json().)
This can potentially be very confusing, because you—as a reasonable human person—might assume that the CSV file’s data is available, when in fact it hasn’t finished loading yet. A common mistake is to include references to the external data outside of the callback function. Save yourself some headaches and make sure to reference your data only from within the callback function (or from within other functions that you call within the callback function).
Personally, I like to declare a global variable first, then call d3.csv() to load the data. Within the callback function, I copy the data into my global variable (so it’s available to all of my subsequent functions), and finally I call any functions that rely on that data being present.
我承认,这与我个人对程序范式的理解相矛盾。但 console.log 仍然让我困惑。正如 Lars 所说,console.log 不是异步的,但它以另一种顺序评估两个变量?这不是异步的定义吗?
最佳答案
这是因为 d3.csv
是一个异步调用。也就是说,d3.csv
block 之后的代码可以在调用返回并且数据可用之前运行。这就是 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);
});
关于javascript - d3.js中的数组,console.log可以显示其内容,但其长度为0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25037528/