背景信息:我尝试多次查询CrisisNET API,以查找每天在一系列日期内提交的报告数量。
问题:在使用totals数组绘制d3图表之前,如何检查所有异步函数是否已完成?
代码:
var format = d3.time.format.iso,
min = format.parse('2014-06-01'),
max = format.parse('2014-07-01'),
range = d3.time.day.utc.range(min, max);
totals = [];
for (var i = 0; i < range.length - 1; i++) {
var request = (function(before, after) {
var url = 'http://api.crisis.net/item?'
+ '&before=' + format(before)
+ '&after=' + format(after)
+ '&placeName=Syria'
+ '&limit=0'
+ '&apikey=[apikey]';
d3.json(url, function(error, data) {
var total = {
'date': after,
'total': data.total
};
totals.push(total);
});
}(range[i + 1], range[i]));
}
提前感谢您的帮助。我是JavaScript的新手,我仍在尝试理解回调,异步函数等。
答案 0 :(得分:1)
如果您知道自己已经完成了多少函数,并且每个函数都有回调函数,那么您可以使用包装函数来计算它们,并在它们全部执行后执行其他操作。像这样:
function asyncCounter(numCalls, callback){
this.callback = callback;
this.numCalls = numCalls;
this.calls = 0;
};
asyncCounter.prototype.increment = function(){
if(this.calls++ === this.numCalls){
this.callback();
}
};
然后创建一个asyncCounter
对象,并在每次读取JSON时递增它:
var myAsyncCounter = new asyncCounter(numCallsExpected, callback);
...//code outside the JSON calls
d3.json(url, function(error, data) {
... //code you want to execute before incrementing the counter
myAsyncCounter.increment();
}
{p> callback
将在d3.json
调用中的所有代码完成后执行。
答案 1 :(得分:0)
这是我到目前为止所提出的问题。它有效,但我确信必须有更好的方法!
var format = d3.time.format.iso,
min = format.parse('2014-06-01'),
max = format.parse('2014-07-01'),
range = d3.time.day.utc.range(min, max);
totals = [];
for (var i = 0; i < range.length - 1; i++) {
var request = (function(before, after) {
var url = 'http://api.crisis.net/item?'
+ '&before=' + format(before)
+ '&after=' + format(after)
+ '&placeName=Syria'
+ '&limit=0'
+ '&apikey=[apikey]';
d3.json(url, function(error, data) {
var total = {
'date': after,
'total': data.total
};
totals.push(total);
ready();
});
}(range[i + 1], range[i]));
}
function ready() {
if (totals.length === range.length - 1) {
// Draw chart here
}
}
答案 2 :(得分:0)
您可以为加载数据时创建回调,并为变量调用次数创建变量。然后,当调用次数等于数据集中必须包含的项目数时,您就可以进行可视化了:
var itemsLoaded = 0;
function dataLoaded() {
itemsLoaded++;
if (itemsLoaded === range.length - 1) {
createVisualization();
}
}
然后在你的d3.json回调中,你可以在项目被推入dataLoaded
后致电totals
:
d3.json(url, function(error, data) {
var total = {
'date': after,
'total': data.total
};
totals.push(total);
dataLoaded();
});
如果totals
中元素的顺序对您非常重要,您可能希望显式使用索引,而不是.push
将它们放入数组中:
d3.json(url, function(error, data) {
var total = {
'date': after,
'total': data.total
};
totals[i] = total;
dataLoaded();
});
另外,在评估变量request
的函数时要小心语法。您需要确保首先评估表达式,然后调用它。
而不是......
var request = (function(before, after) {/*...*/}(range[i+1], range[i]));
......看起来应该是这样的(看看parens):
var request = (function(before, after) {/*...*/})(range[i+1], range[i]);