Javascript 投票服务器。 这会导致堆栈溢出吗?

发布于 2024-07-27 17:07:37 字数 588 浏览 3 评论 0原文

我不太熟悉每个浏览器上每个 javascript 实现的细节。 但我确实知道使用 setTimeout 时,传入的方法会在单独的线程上调用。 那么,在方法内部递归地使用 setTimeout 会导致其堆栈无限增长,直到导致堆栈溢出吗? 或者它会创建一个单独的调用堆栈并在当前帧失去焦点时销毁它? 这是我想知道的代码。

function pollServer()
{
    $.getJSON("poll.php", {}, function(data){
        window.setTimeout(pollServer, 1000);
    });
}

window.setTimeout(pollServer, 0);

我想每隔一秒左右轮询一次服务器,但不想通过“阻塞循环”浪费 CPU 周期 - 而且我不想在浏览器死机之前设置用户可以访问页面的时间限制。

编辑

使用 firebug,我设置了一些断点,并通过查看“Script -> Stack”面板看到调用堆栈实际上只是“pollServer”,并且每次调用都不会增长。 这很好——但是,JS 的其他实现是否有不同的行为?

I am not too familiar with the specifics of every javascript implementation on each browser. I do know however that using setTimeout, the method passed in gets called on a separate thread. So would using a setTimeout recursively inside of a method cause its stack to grow indefinitely until it causes a Stack Overflow? Or would it create a separate callstack and destroy the current frame once it goes out of focus? Here is the code that I'm wondering about.

function pollServer()
{
    $.getJSON("poll.php", {}, function(data){
        window.setTimeout(pollServer, 1000);
    });
}

window.setTimeout(pollServer, 0);

I want to poll the server every second or so, but do not want to waste CPU cycles with a 'blocking loop' - also I do not want to set a timelimit on how long a user can access a page either before their browser dies.

EDIT

Using firebug, I set a few breakpoints and by viewing the "Script -> Stack" panel saw that the call stack is literally just "pollServer" and it doesn't grow per call. This is good - however, do any other implementations of JS act differently?

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

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

发布评论

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

评论(4

稀香 2024-08-03 17:07:37

我不确定它是否会造成堆栈溢出,但如果周期恒定,我建议您使用setInterval

这就是 prototype 实现其 PeriodicalExecuter 的方式。

// Taken from Prototype (www.prototypejs.org)
var PeriodicalExecuter = Class.create({
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  execute: function() {
    this.callback(this);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.execute();
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
});

I am not sure if it would create a stack overflow, but I suggest you use setInterval if the period is constant.

This is how prototype implements its PeriodicalExecuter.

// Taken from Prototype (www.prototypejs.org)
var PeriodicalExecuter = Class.create({
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  execute: function() {
    this.callback(this);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.execute();
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
});
街角迷惘 2024-08-03 17:07:37

setTimeout 在事件泵循环中稍后的某个时间执行。 传递给 setTimeout 的函数不是延续。

如果您停下来想一想,超时函数共享调用堆栈有什么有用的目的或证据。

  • 如果它们被共享,那么从 setter 到超时函数将共享什么堆栈?
  • 假设设置器可以执行一些返回并弹出一些帧 - 将传递什么?
  • 超时函数会阻塞原来的线程吗?
  • setTimeout函数后面的语句是否在超时执行后才执行?

一旦你回答了这些问题,很明显答案是

setTimeout executes sometime later in the future in the event pump loop. Functions passed to setTimeout are not continuations.

If you stop and think about it, what useful purpose or evidencec is there that the call stack is shared by the timeout function.

  • If they were shared what stack would be shared from the setter to the timeout function ?
  • Given the setter can do a few returns and pop some frames - what would be passed ?
  • Does the timeout function block the original thread ?
  • Does the statement after the setTimeout function execute after the timeout executes ?

Once you answer those questions it clearly becomes evident the answerr is NO.

爱,才寂寞 2024-08-03 17:07:37

setTimeout 不会增加调用堆栈,因为它会立即返回。 至于你的代码是否会在任何浏览器中无限期地运行,我不确定,但似乎有可能。

setTimeout does not grow the callstack, because it returns immediately. As for whether your code will run indefinitely in any browser, I'm not sure, but it seems likely.

说好的呢 2024-08-03 17:07:37

看一下 jQuery“SmartUpdater”插件。

http://plugins.jquery.com/project/smartupdater

提供以下功能:

  • stop() - 停止更新。
  • restart() - 暂停后开始更新,并将时间间隔重置为 minTimeout。
  • 继续() - 暂停后开始更新,而不重置时间间隔。
  • 状态属性 - 显示当前状态(正在运行|正在停止|未定义)
  • 仅在新数据与旧数据不同时更新
  • 每次数据未更改时乘以时间间隔
  • 通过在“maxFailedRequests”之后停止请求数据来处理 ajax 失败

take a look at the jQuery "SmartUpdater" plugin.

http://plugins.jquery.com/project/smartupdater

Following features are available:

  • stop() - to stop updating.
  • restart() - to start updating after pause with resetting time interval to minTimeout.
  • continue() - to start updating after pause without resetting time interval.
  • status attribute - shows current status ( running | stopping | undefined )
  • updates only if new data is different from the old one.
  • multiplies time interval each time when data is not changed.
  • handle ajax failures by stopping to request data after "maxFailedRequests".
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文