2013-04-29 6 views
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);

браузер падает.

Спасибо.

+1

Никогда не применяйте когда-либо использовать 'eval' там! (Не для разбора JSON, а не когда он уже разобран) – Bergi

+0

это не рекурсивная функция. – Zo72

+0

Помните, что $ .get является асинхронным, поэтому вызов doSomething до завершения всех вызовов может вызвать проблемы, если для выполнения вызовов требуется более 10 секунд. Вы можете использовать $ .ajax и установить async = false. –

ответ

8

Я думаю, что вы хотите это:

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

Также стоит отметить, что если ваш вызов AJAX занимает более 10 секунд, чтобы завершить вы можете начать видеть некоторые «глюки». Возможно, подумайте о переходе таймаута внутрь обратного вызова .done (это означало бы, что он снова запустится 10 секунд после ajax завершен). Однако это всего лишь предложение, если это не подходит вашим потребностям, тогда вы можете сохранить его таким, каким оно есть. Кроме того, это может оказаться неприемлемым, поскольку вы вызываете ajax в цикле for, и вы можете получить больше таймаутов, чем вы хотите, если вы его не используете правильно.

+1

Большое спасибо за ваш ответ!поскольку вы были первыми, кто опубликовал его, я дам вам галочку! :) – msqar

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); 
+0

Спасибо! это был правильный ответ, но мусефан ответил первым! я бы тоже хотел дать вам галочку: «(вы были очень полезны! – msqar

+0

@msqar на самом деле ни один ответ не является самым чистым решением ... – Alnitak

+0

@Alnitak позвольте мне проверить ваш. – msqar

3

Это обычно в этом случае делать тяжелую работу во внутренней функции, с первоначально поставляемый через замок:

function doStuff(graphName) { 
    (function loop() { 
     // draw the graph using "graphName" from the outer scope 
     ... 
     setTimeout(loop, 10000); 
    })(); // invoke immediately to start the process 
} 

0 0 и дополнительную оболочку функции вокруг этого вызова, поскольку вы можете просто передать ссылку на внутреннюю функцию.

Это также хорошо работает с 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) }); 
+0

Включение тайм-аута в обратный вызов ajax здесь немного усложняется, поскольку у него есть 3 из них параллельный :-) 10s должно быть хорошо, и он мог использовать параметр «timeout», чтобы избежать сбоев ... – Bergi

+0

@ Bergi nah, это triv ial с вызовом '$ .when'. – Alnitak

+0

'$ .when.apply ($, [" hour "," day "," month "]. Map (function (g) {return $ .get (" getchartdata ", {" graphName ": graphName," subgroup " : g}). done (function (d) {drawChart (d, d [0] [0], d [0] [1]);});})). done (setTimeout.bind (window, doStuff. bind (this, graphName), 10000)); 'может быть тривиальным для нас, но не для новичков :-) – Bergi

Смежные вопросы