0

我得到了这个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);

浏览器崩溃。

谢谢。

4

3 回答 3

8

我想你想要的是这样的:

setTimeout(function() { 
    doStuff(graphName); 
}, 10000);

还值得注意的是,如果您的 AJAX 调用需要超过 10 秒才能完成,您可能会开始看到一些“故障”。也许考虑将超时移动到.done回调内部(这意味着它会在 ajax 完成后10 秒再次运行)。但是,这只是一个建议,如果这不适合您的需求,那么您可以保持原样。此外,这可能不适合您在for循环中调用 ajax,如果您没有正确实现它,您最终可能会遇到比您想要的更多的超时

于 2013-04-29T16:12:33.850 回答
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) });
于 2013-04-29T16:17:10.837 回答
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);
}

另一种可能性是为下一次调用绑定参数:doStuff

setTimeout(doStuff.bind(this, graphName), 10000);
于 2013-04-29T16:15:45.677 回答