我有这个javascript递归函数:
function doStuff(graphName) {
var groupArray = new Array();
groupArray[0] = "hour";
groupArray[1] = "day";
groupArray[2] = "month";
for(var i = 0; i < groupArray.length; i++) {
$.get("getchartdata", {"graphName" : graphName, "subgroup" : groupArray[i]})
.done(function(jsonData){
var data = eval(jsonData);
drawChart(data, data[0][0], data[0][1]);
});
}
setTimeout(doStuff, 10000);
}
现在问题是它第一次运行得很好,但是再次尝试10秒后,它会显示错误:
TypeError: data[0] is undefined in drawChart(data, data[0][0], data[0][1]);
为什么会发生这种情况?
如果我在setTimeout(doStuff(graphName), 10000);
浏览器崩溃。
感谢。
答案 0 :(得分:8)
我认为你想要的是:
setTimeout(function() {
doStuff(graphName);
}, 10000);
值得注意的是,如果您的AJAX调用需要10秒以上才能完成,您可能会开始看到一些“故障”。也许考虑将超时移到.done
回调内(这意味着在 ajax完成后它再次运行10秒)。但是,这只是一个建议,如果这不符合您的需求,那么您可以保持原样。此外,这可能不合适,因为您在for
循环中调用ajax,如果您没有正确实现它,您可能会得到比您想要的更多超时
答案 1 :(得分:3)
如果您想传递graphname
参数,则需要明确这样做!好像你想要
function doStuff(graphName) {
var groupArray = ["hour", "day", "month"];
for(var i = 0; i < groupArray.length; i++) {
$.get("getchartdata", {"graphName" : graphName, "subgroup" : groupArray[i]})
.done(function(data){
drawChart(data, data[0][0], data[0][1]);
});
}
setTimeout(function() {
doStuff(graphName); // again
}, 10000);
}
另一种可能性是bind下一个doStuff
调用的参数:
setTimeout(doStuff.bind(this, graphName), 10000);
答案 2 :(得分:3)
在这种情况下,通常在内部函数中进行艰苦的工作,通过闭包提供最初提供的参数:
function doStuff(graphName) {
(function loop() {
// draw the graph using "graphName" from the outer scope
...
setTimeout(loop, 10000);
})(); // invoke immediately to start the process
}
使用闭包避免了重复传递参数的重复,以及围绕该调用的附加函数包装器,因为您可以将引用传递给内部函数。
这也适用于AJAX - 只需将setTimeout
调用放在.done
处理程序中。当您正在进行三次AJAX调用时,请在内部函数中尝试此操作,该函数将在启动计时器之前等待所有三个AJAX调用完成:
var def = [];
for (var i = 0; i < groupArray.length; i++) {
def[i] = $.get("getchartdata", {"graphName" : graphName, "subgroup" : groupArray[i]})
.done(function(data) {
drawChart(data, data[0][0], data[0][1]);
});
}
// wait for all three deferred objects to be resolved
$.when.apply($, def).done(function() { setTimeout(loop, 10000) });