Код ниже рекурсивно использует память - PullRequest
0 голосов
/ 24 ноября 2011

Я делаю очень простой Comet-подобный длинный опрос в JavaScript. Код, приведенный ниже, работает, но рекурсивно ли он вызывает себя и потребляет ресурсы?Как мне сказать?

РЕДАКТИРОВАТЬ: Код отредактирован в соответствии с предложением Dogberts

$(document).ready(function () {
    function doSuccess(data) {
        $('#res').html(data.time + "<br/>" + data.data);
        startAjax();
    }
    function doError(jqXHR, textStatus, errorThrown) {
        $('#res').html(textStatus + ":" + errorThrown);
        startAjax();
    }
    function startAjax() {
        $.ajax({
            url: 'http://127.0.0.1:12345/',
            dataType: 'jsonp',
            success: doSuccess,  //Edit: updated as per Dogbert's suggestion
            error: doError
        });
    }
    startAjax();
});

Я запустил http://home.orange.nl/jsrosman/ против него, и он выглядитбудь в порядке (я просто профессионально параноик) startAjax вызывает (ну, называет назад) doSuccess, который вызывает startAjax

Ответы [ 4 ]

3 голосов
/ 24 ноября 2011

Нет, это не должно быть никаких дополнительных ресурсов. Вы правильно вызываете метод после того, как старый запрос был выполнен.

На заметку, это

        success: function (data) {
            doSuccess(data);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            doError(jqXHR, textStatus, errorThrown);
        }

можно записать как

success: doSuccess,
error: doError
1 голос
/ 24 ноября 2011

В этом коде нет рекурсии, startAjax выходит практически сразу после его вызова.Вы могли бы обойтись без переопределения функций при каждом вызове, хотя бы минимизировать использование памяти, но старые функции в конечном итоге все равно были бы gc, поскольку ссылаться на них невозможно.Ответ @ Догберта показывает, как избежать переопределения функций, но в этом нет ничего критического, поскольку в любом случае не образуются постоянные замыкания.

Формирование замыкания определяется как: когда вызывается внешняя функция, которая определяет внутреннюю функцию (и),и что (эти) внутренние функции доступны для выхода из внешней функции.

Теперь, если вы выполняете ajax в синхронном режиме, startAjax никогда не завершится, и этопродолжал бы вызывать больше startAjax косвенно, и вы бы в конечном итоге достигли максимального размера стека вызовов.Не говоря уже о том, что ваш пользовательский интерфейс будет заблокирован в 100% случаев.

Например, запустите его в Google Chrome, и вы получите:

RangeError: Maximum call stack size exceeded

function success(){
startAjax();
}

function error(){
startAjax();
}

function startAjax(){
synchronousAjax( success, error );
}

function synchronousAjax( success, error){
Math.random() < 0.5 ? success() : error();
}

startAjax();
1 голос
/ 24 ноября 2011

Для меня это выглядит нормально: каждый новый запрос выдается после истечения срока действия старого

0 голосов
/ 24 ноября 2011

Первоначально комментарий к вашему вопросу, но он стал немного длиннее, чем я ожидал ...

Для меня это нормально с точки зрения утечек памяти - вы нигде не назначаете никаких переменных, так что нет проблем для сборщика мусора.

Однако вы можете столкнуться с переполнением стека, учитывая рекурсивную природу этого подхода - он никогда не «выдвигается», чтобы разматывать стек. Не могли бы вы вместо этого использовать setTimeout для периодического запуска процесса?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...