Is the code below using memory recursively

2019-09-09 07:30发布

问题:

I'm doing a very simple Comet-like long polling in JavaScript The code below seems to work, but is it recursively calling itself and eating resources? How do I tell ?

EDIT: Code edited as per Dogberts suggestion

$(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();
});

I've run http://home.orange.nl/jsrosman/ against it and it looks to be OK there (I'm just being professionally paranoid) startAjax calls (well callsBack) to doSuccess which calls startAjax

回答1:

No, this shouldn't be eating any extra resources. You're properly calling the method after the old request has been completed.

On a side note, this

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

could be written as

success: doSuccess,
error: doError


回答2:

To me it looks ok: each new request is issued after the old one has expired



回答3:

There is no recursion in that code, startAjax exits pretty much immediately after it's called. you could do without redefining functions on every call though to minimize the memory use but the old functions are gc'd eventually anyway since there is no way to reference them. @Dogbert's answer shows how to avoid redefining the functions, but it's nothing critical as there are no permanent closures formed anyway.

Closure forming defined as: when an outer function is called that defines an inner function(s), and that(those) inner function(s) is(are) available after the outer function has exited.

Now, if you were to do the ajax in synchronous mode, then startAjax would never exit and it would keep calling more startAjax indirectly, and you would eventually reach the maximum call stack size. Not to mention your UI would be locked 100% of the time.

For example run this in google chrome and you will get:

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();


回答4:

Originally a comment on your question, but it got a bit longer than i expected...

This looks fine to me in terms of memory leaks - you're not assigning any variables anywhere so no problem for the garbage collector.

However, you may hit a stack overflow eventually, given the recursive nature of this approach - it never "bottoms out" to unwind the stack. Could you instead use setTimeout to initiate the process periodically?