下面的代码是否递归地使用内存
我正在用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
该代码中没有递归,
startAjax
在调用后几乎立即退出。您可以不用在每次调用时重新定义函数,尽管可以最大限度地减少内存使用,但旧函数最终会被垃圾回收,因为无法引用它们。 @Dogbert 的答案显示了如何避免重新定义函数,但这并不重要,因为无论如何都没有形成永久闭包。闭包形成定义为:当调用定义内部函数的外部函数时,并且该内部函数在外部函数退出后可用。
现在,如果您要以同步模式执行 ajax,那么
startAjax
将永远不会退出,并且它会继续间接调用更多startAjax
,最终将达到最大调用堆栈尺寸。更不用说你的 UI 将 100% 的时间被锁定。例如,在 google chrome 中运行此命令,您将得到:
RangeError:超出最大调用堆栈大小
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 morestartAjax
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
最初是对你的问题的评论,但它比我预期的要长一些......
就内存泄漏而言,这对我来说看起来很好 - 你没有在任何地方分配任何变量,所以垃圾收集器没有问题。
然而,考虑到这种方法的递归性质,您最终可能会遇到堆栈溢出 - 它永远不会“触底”来展开堆栈。您可以使用
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?不,这不应该消耗任何额外的资源。您在旧请求完成后正确调用该方法。
附带说明一下,这
可以写成
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
could be written as
对我来说,这看起来不错:每个新请求都是在旧请求过期后发出的
To me it looks ok: each new request is issued after the old one has expired