定期调用函数,堆栈无限增长

问题描述 投票:0回答:1

我有以下 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 之间的
最短
时间。

javascript settimeout ajax-polling
1个回答
1
投票

这是异步堆栈跟踪的结果。我不知道是否有可能破坏异步堆栈,也不知道浏览器中是否有措施来限制异步堆栈的深度以防止溢出/泄漏。

下面的代码做了同样的事情:

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

它不会添加到异步堆栈。

© www.soinside.com 2019 - 2024. All rights reserved.