我有以下 JavaScript 代码,并注意到堆栈正在无限增长。
https://jsfiddle.net/uok7vz9b/
(function () {
async function poll() {
try {
// await fetch ...
} catch (err) {
console.error("Error: ", err);
} finally {
console.trace();
start();
}
}
function start() {
setTimeout(poll, 2000);
}
document.addEventListener("DOMContentLoaded", poll, {once: true});
})();
第一个输出是:
console.trace() _display:118:15
poll https://fiddle.jshell.net/_display/?editor_console=true:118
(Async: EventListener.handleEvent)
<anonymous> https://fiddle.jshell.net/_display/?editor_console=true:127
<anonymous> https://fiddle.jshell.net/_display/?editor_console=true:128
第二个输出:
console.trace() _display:118:15
poll https://fiddle.jshell.net/_display/?editor_console=true:118
(Async: setTimeout handler)
start https://fiddle.jshell.net/_display/?editor_console=true:124
poll https://fiddle.jshell.net/_display/?editor_console=true:119
(Async: EventListener.handleEvent)
<anonymous> https://fiddle.jshell.net/_display/?editor_console=true:127
<anonymous> https://fiddle.jshell.net/_display/?editor_console=true:128
...等等。
我不太明白为什么,因为我认为
setTimeout
不会阻塞,只是启动一个新的计时器。所以我期望 poll
函数完成,然后用干净的堆栈再次触发它。
我环顾四周,并没有真正找到任何好的例子 “在页面加载时执行一次函数,然后定期执行”。我不想使用
setInterval
,因为长时间运行的 AJAX 调用可能会超过超时时间。但超时应该是两次调用 poll
之间的最短时间。
这是异步堆栈跟踪的结果。我不知道是否有可能破坏异步堆栈,也不知道浏览器中是否有措施来限制异步堆栈的深度以防止溢出/泄漏。
下面的代码做了同样的事情:
(function() {
const delay = (duration) => new Promise(r => setTimeout(() => r(), duration))
async function poll() {
for (;;) {
try {
// await fetch ...
} catch (err) {
console.error("Error: ", err);
} finally {
console.trace();
}
await delay(2000)
}
}
document.addEventListener("DOMContentLoaded", poll, {
once: true
});
})();
它不会添加到异步堆栈。