2012-05-31 4 views
0

Итак, у меня есть приложение для javascript, которое получает пару чисел с сервера каждую минуту (или что-то еще), и в течение минуты он обновляет div каждую секунду (или что-то еще), чтобы значение, отображаемое в div постепенно увеличивается от первого значения до второго. Это коротко, я отправлю код в нижней части вопроса.Почему этот JavaScript хранит всю мою память?

Функция содержит две вспомогательные функции: один из них выполняет вызов ajax для обновления двух значений, один из которых обновляет содержимое div значением где-то между двумя значениями. Функция ajax использует setInterval для планирования функции обновления div, когда у нее есть ответ от сервера, и когда функция обновления div обнаруживает, что пришло время обновить два значения, она очищает заданный интервал и вызывает функцию ajax. Эти две функции, таким образом, продолжают называть друг друга навсегда.

Я объявлял каждую переменную, используемую двумя вспомогательными функциями во внешней функции, поэтому ни одна из подфункций не создает никаких новых переменных, и обе подфункции разрешаются полностью завершать каждый раз в любом случае (благодаря setInterval в функции ajax).

Использование памяти увеличивается почти каждую секунду, что должно быть каждый раз, когда вы вызываете doDivRefresh, но я не понимаю, что он делает с новой памятью каждый раз, когда он вызывается - он не создает никаких переменных.

Помощь!

/** 
* 
* Periodically gets the latest values for a stat and changes the contents of a 
* div so that is ticks up from the previous value to the latest value 
* 
* @param divID 
*   The id of the div to update 
* @param URL 
*   The URL that provides the values 
* @param updateDivFrequency 
*   How often the value displayed in the div is updated, in 
*   miliseconds 
* @param updateDataFrequency 
*   How often the underlying data is updated from the server, in 
*   seconds 
* 
*/ 
function updateStatOverPeriod(divID, URL, updateDivFrequency, updateDataFrequency) 
{ 
    var somethingDoer = new function() 
    { 
    }; 
    var request = new XMLHttpRequest(); 
    var currentValue = ""; 
    var previousValue = ""; 
    var latestValue = ""; 
    var it = 0; 
    var currentTime = new Date(); 
    var endTime = new Date().getTime(); 

    function doDivRefresh(endTime) 
    { 
     if (currentValue != null) 
     { 
      currentValue = currentValue + it; 
      document.getElementById(divID).innerHTML = addCommas(parseInt(currentValue)); 
     } 
     else 
     { 
      document.getElementById(divID).innerHTML = "<DIV CLASS=\"error_message\">No data</DIV>"; 
     } 
     // If it's time to refresh the data end this loop and call the starting 
     // off method again 
     currentTime = new Date(); 
     if (currentTime.getTime() >= endTime) 
     { 
      clearInterval(somethingDoer); 
      doAJAX(); 
     } 
    } 

    function doAJAX() 
    { 
     // If browser supports javascript 
     if (window.XMLHttpRequest) 
     { 
      // Connect to the server and get the new pair of values 
      request = new XMLHttpRequest(); 
      request.open('get', URL); 
      request.onreadystatechange = function() 
      { 
       // Once... 
       if (request.readyState == 4) 
       { 
        // we've got... 
        if (request.status == 200) 
        { 
         // the response 
         if (request.responseText) 
         { 
          // Parse the response and work out our iterator 
          previousValue = parseFloat(request.responseText.split("&")[0]); 
          latestValue = parseFloat(request.responseText.split("&")[1]); 
          if ((previousValue == 0) || (latestValue == 0)) 
          { 
           it = parseFloat('0.00'); 
          } 
          else 
          { 
           it = parseFloat((latestValue - previousValue)/(updateDataFrequency/updateDivFrequency)); 
          } 
          // Set up the doRefreshDiv function in a loop that 
          // will exit and re-call this function 
          // once updateDataFrequency has elapsed 
          currentValue = previousValue; 
          endTime = new Date().getTime() + updateDataFrequency; 
          doDivRefresh(endTime); 
          somethingDoer = setInterval(function() 
          { 
           doDivRefresh(endTime); 
          }, updateDivFrequency); 
          alert("end of ajax response function()"); 
         } 
         else 
         { 
          document.getElementById(divName).innerHTML = "<DIV CLASS=\"error_message\">Error - no data received from server</DIV>"; 
         } 
        } 
        else 
        { 
         document.getElementById(divName).innerHTML = "<DIV CLASS=\"error_message\">Error - server returned " + request.status + "</DIV>"; 
        } 
       } 
      }; 
      request.send(null); 
     } 
     else 
     { 
      console.error("No window.XMLHttpRequest, does this browser support AJAX?"); 
     } 
     alert("end of doAJAX()"); 
    } 

    // Start 
    updateDataFrequency = updateDataFrequency * 1000; 
    doAJAX(); 
} 
+2

Я думаю, что он голоден (или что-то еще). С другой стороны, вы понимаете, что вы создаете 'новые XMLHttpRequest()' s? 'new Date()' s? Новая 'function()'? Хотя сбор мусора должен заботиться о них, а как насчет новых текстовых данных в div? Откуда вы знаете, что это JavaScript, а не дополнения к DOM, которые яростно едят вашу драгоценную память? И какой браузер вы используете? – Zeta

+0

Сборщик мусора, если он свободен для выпуска памяти всякий раз, когда он сочтет нужным, вы ждали, не исчезнет ли память через какое-то время? Как большой прирост вы видите за звонок? –

+1

'setInterval() -> clearInterval() -> setInterval()' Почему вы не используете 'setTimeout()', который даст то же самое с меньшими усилиями и будет менее подвержен ошибкам – Andreas

ответ

1

Это первые четыре строки скорректированные в соответствии с jslint.com:

function updateStatOverPeriod(divID, URL, updateDivFrequency, updateDataFrequency) { 
    "use strict"; 
    var somethingDoer = function() {}; 
    var request = new XMLHttpRequest(); 

Вставьте код там и проверить общие JS ошибки. Кажется, этот код был либо преобразован с другого языка на JavaScript, либо кого-то, кто не знаком с JavaScript ...

См. Мой ответ javascript memory leak для устранения утечек памяти. Я все еще думаю, что Drip - очень хороший инструмент для поиска и понимания утечек памяти.

0

Я согласен с тем, что new Date() всегда будет дорогостоящим. Теперь, когда вы просто хотите, чтобы этот код выполнялся для обновления значений с регулярным интервалом, вы можете использовать setTimeout("doAJAX()",2000);, и вы можете указать интервал в миллисекундах вместо проверки с помощью функции даты. Это должно помочь, и в другом случае вы можете использовать jquery.Ajax, если вам интересно, потому что вы сможете сосредоточиться на своей области интересов, а не на сделке с XMLHttpRequest.

0

[глава пощечина]

Спасибо за ответы, ребята, но реальная проблема была опечатка в элементе вызывающего сценария. Из-за того, где я хотел поставить *, сценарий вызывался примерно раз в миллисекунду, а не раз в минуту, как предполагалось!

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