下面的代码是否递归地使用内存

发布于 2024-12-17 17:45:34 字数 883 浏览 0 评论 0原文

我正在用 JavaScript 进行一个非常简单的类似 Comet 的长轮询 下面的代码似乎可以工作,但是它是否递归调用自身并消耗资源?我怎么知道?

编辑:根据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 调用(以及callsBack)到 doSuccess 调用 startAjax

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

秋心╮凉 2024-12-24 17:45:35

该代码中没有递归,startAjax 在调用后几乎立即退出。您可以不用在每次调用时重新定义函数,尽管可以最大限度地减少内存使用,但旧函数最终会被垃圾回收,因为无法引用它们。 @Dogbert 的答案显示了如何避免重新定义函数,但这并不重要,因为无论如何都没有形成永久闭包。

闭包形成定义为:当调用定义内部函数的外部函数时,并且该内部函数在外部函数退出后可用。

现在,如果您要以同步模式执行 ajax,那么 startAjax 将永远不会退出,并且它会继续间接调用更多 startAjax,最终将达到最大调用堆栈尺寸。更不用说你的 UI 将 100% 的时间被锁定。

例如,在 google chrome 中运行此命令,您将得到:

RangeError:超出最大调用堆栈大小

function success(){
startAjax();
}

function error(){
startAjax();
}

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

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

startAjax();

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();
明月夜 2024-12-24 17:45:35

最初是对你的问题的评论,但它比我预期的要长一些......

就内存泄漏而言,这对我来说看起来很好 - 你没有在任何地方分配任何变量,所以垃圾收集器没有问题。

然而,考虑到这种方法的递归性质,您最终可能会遇到堆栈溢出 - 它永远不会“触底”来展开堆栈。您可以使用 setTimeout 定期启动该过程吗?

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?

南汐寒笙箫 2024-12-24 17:45:34

不,这不应该消耗任何额外的资源。您在旧请求完成后正确调用该方法。

附带说明一下,这

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

可以写成

success: doSuccess,
error: doError

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
︶葆Ⅱㄣ 2024-12-24 17:45:34

对我来说,这看起来不错:每个新请求都是在旧请求过期后发出的

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文