【发布时间】:2021-10-06 22:34:14
【问题描述】:
我正在实现长轮询系统的客户端。我读到的所有内容都说,为了避免无限的堆栈深度,不要进行直接递归调用,而是使用 setTimeout() 间接调用,因此每次迭代都从一个干净的堆栈开始。实现是:
function pollForEvents() {
$.get(
"GetEventLP",
null,
function(eventData) {
console.log("Got event at "+new Date()+": "+JSON.stringify(eventData));
setTimeout(function() {pollForEvents();}, 1); // Using setTimeout() avoids infinite recurssion stack growth
}).fail(function(xhr, status, err) {
console.log("Long poll faied at "+new Date()+": "+util.getServerErrorText(xhr));
// Wait before we try again to avoid fast failure polling
setTimeout(function() {pollForEvents();}, 60000);
});
}
我让它运行了一些迭代,然后在 $.get() 调用处设置一个断点。在下一次迭代中,它会中断,Chrome 会显示与迭代次数一样深的调用堆栈 - 例如它无限增长。我是不是误会了什么?这似乎是基于不断增加的调用堆栈大小的内存泄漏。
这是 Chrome 在 6 次迭代后显示的调用堆栈,请注意重复的 pollForEvents() 帧。
pollForEvents (index.js?v=1.02:406)
(anonymous) (index.js?v=1.02:411)
setTimeout (async)
(anonymous) (index.js?v=1.02:411)
i (jquery-3.1.1.min.js:2)
fireWith (jquery-3.1.1.min.js:2)
A (jquery-3.1.1.min.js:4)
(anonymous) (jquery-3.1.1.min.js:4)
load (async)
send (jquery-3.1.1.min.js:4)
ajax (jquery-3.1.1.min.js:4)
r.<computed> (jquery-3.1.1.min.js:4)
pollForEvents (index.js?v=1.02:406)
(anonymous) (index.js?v=1.02:411)
setTimeout (async)
(anonymous) (index.js?v=1.02:411)
i (jquery-3.1.1.min.js:2)
fireWith (jquery-3.1.1.min.js:2)
A (jquery-3.1.1.min.js:4)
(anonymous) (jquery-3.1.1.min.js:4)
load (async)
send (jquery-3.1.1.min.js:4)
ajax (jquery-3.1.1.min.js:4)
r.<computed> (jquery-3.1.1.min.js:4)
pollForEvents (index.js?v=1.02:406)
(anonymous) (index.js?v=1.02:411)
setTimeout (async)
(anonymous) (index.js?v=1.02:411)
i (jquery-3.1.1.min.js:2)
fireWith (jquery-3.1.1.min.js:2)
A (jquery-3.1.1.min.js:4)
(anonymous) (jquery-3.1.1.min.js:4)
load (async)
send (jquery-3.1.1.min.js:4)
ajax (jquery-3.1.1.min.js:4)
r.<computed> (jquery-3.1.1.min.js:4)
pollForEvents (index.js?v=1.02:406)
(anonymous) (index.js?v=1.02:411)
setTimeout (async)
(anonymous) (index.js?v=1.02:411)
i (jquery-3.1.1.min.js:2)
fireWith (jquery-3.1.1.min.js:2)
A (jquery-3.1.1.min.js:4)
(anonymous) (jquery-3.1.1.min.js:4)
load (async)
send (jquery-3.1.1.min.js:4)
ajax (jquery-3.1.1.min.js:4)
r.<computed> (jquery-3.1.1.min.js:4)
pollForEvents (index.js?v=1.02:406)
(anonymous) (index.js?v=1.02:411)
setTimeout (async)
(anonymous) (index.js?v=1.02:411)
i (jquery-3.1.1.min.js:2)
fireWith (jquery-3.1.1.min.js:2)
A (jquery-3.1.1.min.js:4)
(anonymous) (jquery-3.1.1.min.js:4)
load (async)
send (jquery-3.1.1.min.js:4)
ajax (jquery-3.1.1.min.js:4)
r.<computed> (jquery-3.1.1.min.js:4)
pollForEvents (index.js?v=1.02:406)
(anonymous) (index.js?v=1.02:411)
setTimeout (async)
(anonymous) (index.js?v=1.02:411)
i (jquery-3.1.1.min.js:2)
fireWith (jquery-3.1.1.min.js:2)
A (jquery-3.1.1.min.js:4)
(anonymous) (jquery-3.1.1.min.js:4)
【问题讨论】:
-
您确定没有在
success处理程序和fail回调之外调用此函数吗? -
在页面加载过程中调用一次启动轮询过程,其他地方不调用。
-
你是否省略了这个函数中的其他代码?
-
不,这是函数的精确复制/粘贴。我修改了问题以显示 Chrome 在 6 次迭代后拥有的堆栈帧。
-
Chrome 显示可能包含多个堆栈的错误消息。您可以使用开发人员工具上的“性能”选项卡来查看堆栈。
标签: javascript recursion memory-leaks