19

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 或任何更新现有计时器的方法。

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

有更好的方法吗?

谢谢!

4

5 回答 5

14

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

您可以为 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
于 2009-12-24T07:23:38.277 回答
4

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

于 2009-12-24T07:08:02.990 回答
2

另一个包装器:

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!
于 2009-12-24T08:42:39.350 回答
0

它可能不完全是您想要的,但无论如何请看一下,也许您可​​以利用它为您带来好处。

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

解决方案是一个名为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);

PS 要使此解决方案起作用,您需要使用函数扩展 Function 对象,这在Prototypecurry中自动完成。

于 2009-12-24T07:39:40.280 回答
-2

一种可能是这样的:

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

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

于 2009-12-24T07:04:47.183 回答