【问题标题】:how do I ensure I only have one chain of recursive setTimeouts running at once?如何确保我一次只运行一个递归 setTimeouts 链?
【发布时间】:2016-01-15 13:33:53
【问题描述】:

我正在制作一个供个人使用的 chrome 扩展,它将递归调用 setTimeout。我想确保这个扩展在任何情况下都不会意外产生多个 setTimeouts 链。

我已经做到了,当我单击浏览器操作时,它会调用 clearTimeout。但是,我担心当我重新加载扩展时,旧的超时链会继续吗?可能还有其他我没有想到的情况。是否有一种可靠的方法来防止意外创建多个超时链?

似乎没有办法枚举活动的javascript计时器:Viewing all the timouts/intervals in javascript?

【问题讨论】:

  • 你能添加一些代码吗?因为尚不完全清楚您如何“递归调用”setTimeout。无论如何,如果您在后台页面脚本中执行此操作,那么所有计时器将在重新加载时被销毁。只有注入的内容脚本才能生存,除非您还重新加载网页。另外,我建议使用chrome.alarms API。

标签: javascript recursion google-chrome-extension settimeout


【解决方案1】:

我之前解决过类似的案例:

var timer;
function foo(){
  if(!timer)
    timer = setTimeout(function (){
      //should print once every second only
      console.log(new Date());
      timer = null;
      foo();
  }, 1000)
}

foo();
foo();

由于 javascript 在处理下一个事件之前运行同步代码完成,这是安全的。

【讨论】:

    【解决方案2】:

    我的冲动是使用clearTimeout 来抑制竞争超时,但我也喜欢 Johan Gov 的回答,尤其是概括性的回答:

    var setOneTimeout = (function() {
      var timer
      return function(f, timeout) {
        if (!timer) {
          timer = setTimeout(function() {
            timer = null
            f()
          }, timeout)
        }
      }
    })()
    
    setOneTimeout(function() { console.log('foo') }, 500)
    setOneTimeout(function() { console.log('bar') }, 500)
    /* outputs "foo", only. */
    

    或者,如果您将有多个类别的超时并且只希望每个类别中有一个“运行”超时:

    var setNamedTimeout = (function() {
      var timer = {}
      return function(name, f, timeout) {
        if (!timer[name]) {
          timer[name] = setTimeout(function() {
            timer[name] = null
            f()
          }, timeout)
        }
      }
    })()
    
    setNamedTimeout('foo', function() { console.log('foo') }, 500)
    setNamedTimeout('bar', function() { console.log('bar') }, 500)
    setNamedTimeout('bar', function() { console.log('bar') }, 500)
    setNamedTimeout('bar', function() { console.log('bar') }, 500)
    setNamedTimeout('bar', function() { console.log('bar') }, 500)
    setNamedTimeout('foo', function() { console.log('foo') }, 500)
    /* outputs only one instance of "foo" and "bar" */
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-06
      • 2012-01-08
      • 1970-01-01
      • 2011-09-22
      • 1970-01-01
      • 1970-01-01
      • 2019-11-12
      • 1970-01-01
      相关资源
      最近更新 更多