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 秒以上かかる場合は、「グリッチ」が発生する可能性があることにも注意してください。おそらく、タイムアウトをコールバック内に移動することを検討してください (これは、ajax が完了してから.done10 秒後に再度実行されることを意味します)。ただし、これは単なる提案です。これがニーズに合わない場合は、そのままにしておくことができます。また、ループで ajax を呼び出しているため、これは適切ではない可能性があり、for正しく実装しないと、必要以上のタイムアウトが発生する可能性があります。

于 2013-04-29T16:12:33.850 に答える
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 に答える
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ハンドラー内に置くだけです。3 つの AJAX 呼び出しを行っているので、タイマーを開始する前に 3 つの 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 に答える