Я получаю сообщение об ошибке: слишком много рекурсии. Почему это?

#javascript #jquery

#javascript #jquery

Вопрос:

У меня есть функция для обновления графиков на странице. Идея в том, что он постоянно зацикливается и обновляет вызываемую переменную salt . Переменные определены в отдельном файле и называются path , displayTimeFrom , selectedTimeRangeType и target . Вот код цикла, который также реагирует на изменения в графическом интерфейсе:

 $(function () {
    refreshGraphs();
});

var refreshGraphs = function () {
    d = new Date();

    var graphiteUrl = graphs.path   "render/?_salt"   d.getTime()
                  "amp;from=-"   graphs.displayTimeFrom
                  graphs.selectedTimeRangeType
                  "amp;minXStep=0"
                  "amp;until=nowamp;height=800amp;";

    $('#graph-middle').prop("src", graphiteUrl   graphs.target);

    setIntervalAndExecute(refreshGraphs, 30000); // refresh every 30000 milliseconds aka every 30 seconds

    // Execute immediately and after the interval (setInterval only starts after certain amount of time)
    function setIntervalAndExecute(fn, t) {
        fn();
        return (setInterval(fn, t));
    }

    // Change graph to chosen value
    $('#graph-middle').on('click', '#displayTimeFrom', function () {
        graphs.displayTimeFrom = $(this).text();
        refreshGraphs();
    });

    $('#graph-middle').on('click', '#selectedTimeRangeType', function () {
        graphs.selectedTimeRangeType = $(this).text();
        refreshGraphs();
    });
};
  

Когда я запускаю его, он говорит "too much recursion" . Почему это так и как я могу это решить?

Комментарии:

1. Я отредактировал свой ответ. пожалуйста, проверьте

Ответ №1:

Ваша refreshGraphs() функция вызывает себя немедленно (через setIntervalAndExecute() ) при каждом запуске.

Комментарии:

1. Проблема не в этом. Эта рекурсия разрешена, поскольку ожидание составляет 30 секунд. Проблема заключалась в привязке jQuery в функции refreshgraphs . Как только я поместил их в анонимную функцию сверху (документ готов), все было в порядке.

2. @user2609980: Нет; fn() вызов тоже запускает его немедленно.

3. Ну, это не проблема, когда я помещаю код jQuery в $(function() .

4. Я снова смотрю на код. И теперь я вижу, что вы, должно быть, правы. Переместив setIntervalAndExecute в $function() и за пределы refreshGraphs , я думаю, я убедился, что немедленное и рекурсивное выполнение fn() вызывается только один раз (сейчас нет доступа к коду, поэтому не уверен, каким именно было решение). Я посмотрю позже. Тем не менее, код отлично работает месяцами подряд (т. Е. Он обновляет графики каждые 30 секунд …). Мне интересно, вызывает ли jQuery refreshGraphs() какой-то сложный цикл, который просто работает.

Ответ №2:

Следует отметить две вещи:
1. Вы вызываете refreshGraphs() рекурсивно.
2. Вы поместили click обработчики в refreshGraphs() функцию.

Поэтому всякий раз, когда это refreshGraphs() вызывается, оно click снова связывает события, не отменяя привязку предыдущего. Вам нужно либо отменить привязку предыдущего, либо вы можете поместить их $(function () {}) .

Попробуйте любой из них.

 $(function () {
    refreshGraphs();
    // Change graph to chosen value
    $('#graph-middle').on('click', '#displayTimeFrom', function () {
        graphs.displayTimeFrom = $(this).text();
        refreshGraphs();
    });

    $('#graph-middle').on('click', '#selectedTimeRangeType', function () {
        graphs.selectedTimeRangeType = $(this).text();
        refreshGraphs();
    });
});

var refreshGraphs = function () {
    d = new Date();

    var graphiteUrl = graphs.path   "render/?_salt"   d.getTime()
                  "amp;from=-"   graphs.displayTimeFrom
                  graphs.selectedTimeRangeType
                  "amp;minXStep=0"
                  "amp;until=nowamp;height=800amp;";

    $('#graph-middle').prop("src", graphiteUrl   graphs.target);

    setIntervalAndExecute(refreshGraphs, 30000); // refresh every 30000 milliseconds aka every 30 seconds

    // Execute immediately and after the interval (setInterval only starts after certain amount of time)
    function setIntervalAndExecute(fn, t) {
        fn();
        return (setInterval(fn, t));
    }
};
  

Или

 $(function () {
    refreshGraphs();
});

var refreshGraphs = function () {
    d = new Date();

    var graphiteUrl = graphs.path   "render/?_salt"   d.getTime()
                  "amp;from=-"   graphs.displayTimeFrom
                  graphs.selectedTimeRangeType
                  "amp;minXStep=0"
                  "amp;until=nowamp;height=800amp;";

    $('#graph-middle').prop("src", graphiteUrl   graphs.target);

    setIntervalAndExecute(refreshGraphs, 30000); // refresh every 30000 milliseconds aka every 30 seconds

    // Execute immediately and after the interval (setInterval only starts after certain amount of time)
    function setIntervalAndExecute(fn, t) {
        fn();
        return (setInterval(fn, t));
    }

    // Change graph to chosen value
    $('#graph-middle').off('click').on('click', '#displayTimeFrom', function () {
        graphs.displayTimeFrom = $(this).text();
        refreshGraphs();
    });

    $('#graph-middle').off('click').on('click', '#selectedTimeRangeType', function () {
        graphs.selectedTimeRangeType = $(this).text();
        refreshGraphs();
    });
};
  

Комментарии:

1. Лучше объяснить, что вы изменили и почему вы это изменили, а не оставлять OP в недоумении.

Ответ №3:

Решение состоит в том, чтобы вызвать jQuery в анонимной функции вместо пространства имен refreshGraps . Проблема решена.