【问题标题】:JavaScript getTimeout?JavaScript 获取超时?
【发布时间】:2009-12-24 07:01:26
【问题描述】:

Javascript 中的window.setTimeout(和相关的 setInterval)函数允许您安排函数在未来某个时间执行:

id = setTimeout(function, delay);

其中“延迟”是您希望调用函数的未来毫秒数。在此时间过去之前,您可以使用以下命令取消计时器:

clearTimeout(id);

我想要的更新计时器。我希望能够提前或延迟计时器,以便该函数比原计划调用x毫秒。

如果有 getTimeout 方法,你可以这样做:

originally_scheduled_time = getTimeout(id);
updateTimeout(id, originally_schedule_time + new_delay);  // change the time

但据我所知,没有什么像 getTimeout 或任何更新现有计时器的方法。

有没有办法访问预定警报列表并修改它们?

有没有更好的办法?

谢谢!

【问题讨论】:

  • 欢迎来到 StackOverflow。第一个问题很好。
  • 重新标记,因为我相信您正在寻找(并获得)独立于浏览器的解决方案。

标签: javascript settimeout


【解决方案1】:

如果你真的想要这种功能,你需要自己编写。

您可以为 setTimeout 调用创建一个包装器,它将返回一个您可以用来“推迟”计时器的对象:

function setAdvancedTimer(f, delay) {
  var obj = {
    firetime: delay + (+new Date()), // the extra + turns the date into an int 
    called: false,
    canceled: false,
    callback: f
  }; 
  // this function will set obj.called, and then call the function whenever
  // the timeout eventually fires.
  var callfunc = function() { obj.called = true; f(); }; 
  // calling .extend(1000) will add 1000ms to the time and reset the timeout.
  // also, calling .extend(-1000) will remove 1000ms, setting timer to 0ms if needed
  obj.extend = function(ms) {
    // break early if it already fired
    if (obj.called || obj.canceled) return false; 
    // clear old timer, calculate new timer
    clearTimeout(obj.timeout);
    obj.firetime += ms;
    var newDelay = obj.firetime - new Date(); // figure out new ms
    if (newDelay < 0) newDelay = 0;
    obj.timeout = setTimeout(callfunc, newDelay);
    return obj;
  };
  // Cancel the timer...  
  obj.cancel = function() {
    obj.canceled = true;
    clearTimeout(obj.timeout);
  };
  // call the initial timer...
  obj.timeout = setTimeout(callfunc, delay);
  // return our object with the helper functions....
  return obj;
}

var d = +new Date();
var timer = setAdvancedTimer(function() { alert('test'+ (+new Date() - d)); }, 1000);

timer.extend(1000);
// should alert about 2000ms later

【讨论】:

    【解决方案2】:

    我相信不会。更好的方法可能是编写自己的包装器来存储您的计时器(func-ref、延迟和时间戳)。这样,您可以假装通过清除计时器来更新计时器并计算具有更新延迟的副本。

    【讨论】:

    • @jensgram:一个例子将不胜感激:)
    • +1 - 我会早点发帖,但我正在写一个例子;)
    • 谢谢 - 这似乎是答案。有趣的是 {set,clear}{Timeout,Interval} API 并不丰富。
    【解决方案3】:

    另一个包装器:

    function SpecialTimeout(fn, ms) {
        this.ms = ms;
        this.fn = fn;
        this.timer = null;
        this.init();
    }
    
    SpecialTimeout.prototype.init = function() {
        this.cancel();
        this.timer = setTimeout(this.fn, this.ms);
        return this;
    };
    
    SpecialTimeout.prototype.change = function(ms) {
        this.ms += ms;
        this.init();
        return this;
    };
    
    SpecialTimeout.prototype.cancel = function() {
        if ( this.timer !== null ) {
            clearTimeout(this.timer);
            this.timer = null;
        }
        return this;
    };
    

    用法:

    var myTimer = new SpecialTimeout(function(){/*...*/}, 10000);
    
    myTimer.change(-5000); // Retard by five seconds
    myTimer.change(5000); // Extend by five seconds
    myTimer.cancel(); // Cancel
    myTimer.init(); // Restart
    
    myTimer.change(1000).init(); // Chain!
    

    【讨论】:

    • 漂亮的包装器,(比我的干净得多)但“ms”属性没有考虑任何可能已经或可能没有通过的时间......不确定OP是否需要这个
    • 代码写得很好,但是“更改”方法需要正确补偿已经过去的时间。我认为这很容易通过调用 Date.getTime 来添加。 SpecialTimeout 不会存储延迟直到触发,而是存储它应该触发的绝对时间。
    【解决方案4】:

    它可能不是你想要的,但还是看看吧,也许你可以利用它来为你带来好处。

    我的前同事编写了一个很棒的解决方案,它可以创建特殊的处理函数,可以在需要时停止和启动超时。当您需要为悬停事件创建小延迟时,它最广泛使用。就像你想隐藏鼠标悬停菜单时,不是在鼠标离开它的时候,而是在几毫秒之后。但是如果鼠标回来了,你需要取消超时。

    解决方案是一个名为getDelayedHandlers 的函数。例如,您有一个显示和隐藏菜单的函数

    function handleMenu(show) {
        if (show) {
            // This part shows the menu
        } else {
            // This part hides the menu
        }
    }
    

    然后您可以通过这样做为其创建延迟处理程序:

    var handlers = handleMenu.getDelayedHandlers({
        in: 200, // 'in' timeout
        out: 300, // 'out' timeout
    });
    

    handlers 成为一个对象,其中包含两个处理函数,当被调用时取消另一个的超时。

    var element = $('menu_element');
    element.observe('mouseover', handlers.over);
    element.observe('mouseout', handlers.out);
    

    附:要使此解决方案起作用,您需要使用 curry 函数扩展 Function 对象,该函数在 Prototype 中自动完成。

    【讨论】:

      【解决方案5】:

      一种可能是这样的:

      if (this condition true)
      {
        setTimeout(function, 5000);
      }
      elseif (this condition true)
      {
        setTimeout(function, 10000);
      }
      else
      {
        setTimeout(function, 1000);
      }
      

      这取决于你如何构建你的条件或逻辑。谢谢

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-26
        • 2013-06-13
        • 2018-06-09
        • 2017-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多