如何重用此JavaScript超时闭包?

时间:2011-03-24 14:33:23

标签: javascript timeout closures settimeout

我发现了以下一段JavaScript代码(可能在Stack Overflow?)来实现超时:

var delay = (function() {
  var timer = 0;
  return function(callback, ms) {
    clearTimeout(timer);
    timer = setTimeout(callback, ms);
  };
})();

我是JavaScript的新手,所以我仍然试图围绕闭包。如果我在一个地方调用delay(firstCallback, 200),然后在delay(secondCallback, 200)之后调用,则会清除第一个超时回调,而第二个回调会成功执行。

如何在不覆盖其他实例的情况下在不同实例中重用delay? (不确定这些术语是否正确,但希望它能得到我的观点。)因此,在上面的例子中,我希望两个回调都能执行。

感谢您的帮助!

编辑:作为一个实际的例子,我试图在输入字段上缓冲按键事件,这样只有在没有按下任何键200ms后才执行回调。但是我有多个输入字段,当前两个输入字段快速连续有按键事件时,缓冲区会中断。

3 个答案:

答案 0 :(得分:3)

要重复使用它,可以更容易地删除匿名函数并将其用作生成器。

var createDelayManager = function() {
  var timer = 0;
  return function(callback, ms) {
     clearTimeout(timer);
     timer = setTimeout(callback, ms);
  };
}


var delayManagerOne = createDelayManager();
delayManagerOne(firstCallback, 200);

var delayManagerTwo = createDelayManager();
delayManagerTwo(secondCallback, 200);

这是一个工作小提琴: http://jsfiddle.net/HJrM7/

但是,值得注意的是,这个闭包的目的是防止多个回调堆叠在某个对象上。这是一个非常好的闭包,但是可以确保触发的最后一个事件将被采取行动。我使用这种技术可以防止在重绘过程​​中出现闪烁或不需要的鼠标移出事件。

答案 1 :(得分:1)

您正在寻找

Delay = function(callback, ms) {
    this.callback = callback;
    this.ms = ms;
};

Delay.prototype = {
    timer: -1,

    restart: function() {
        if (this.timer != -1) clearTimeout(this.timer);
        this.timer = setTimeout(this.callback, this.ms);
    }
};

var delay1 = new Delay(callback1, 100);
var delay2 = new Delay(callback2, 100);

// on some event1
delay1.restart();

// on some event2
delay2.restart();

关于jsfiddle的示例:http://jsfiddle.net/TF9Tw/1/

答案 2 :(得分:0)

闭包持有内部函数调用之间持续的状态。在这种情况下,它被使用,因此一次只有一个超时。如果您希望一次可以使用多个超时,则可以编写

setTimeout(callback, ms);

编辑:

对于您的示例,最好的解决方案是创建一个像这样的对象

function DelayManager(){}
DelayManager.prototype.timer = 0;
DelayManager.prototype.delay = function(callback, ms) {
  clearTimeout(this.timer);             
  this.timer = setTimeout(callback, ms);   
}
someDelayManager = new DelayManager();

在不使用someDelayManager的情况下,您将使用每个输入元素唯一的某个对象的成员变量。要添加延迟,您可以调用。

someDelayManager.delay(callback, ms);