Как я могу использовать это закрытие тайм-аута JavaScript? - PullRequest
2 голосов
/ 24 марта 2011

Я нашел следующий фрагмент кода 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 в разных случаях, не перезаписывая другие? (Не уверен, что эти термины верны, но, надеюсь, это поможет мне понять.) Итак, в приведенном выше примере я хочу, чтобы оба обратных вызова выполнялись.

Спасибо за вашу помощь!

РЕДАКТИРОВАТЬ: В качестве практического примера я пытаюсь буферизовать события нажатия клавиш в поле ввода, чтобы обратный вызов выполнялся только после того, как ни одна клавиша не была нажата в течение 200 мс. Но у меня есть несколько полей ввода, и в настоящее время буфер разрушается, когда два поля ввода имеют события нажатия клавиши в быстрой последовательности.

Ответы [ 3 ]

3 голосов
/ 24 марта 2011

Для повторного использования легче избавиться от анонимной функции и использовать ее в качестве генератора.

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 голос
/ 24 марта 2011

Вы ищете

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/

0 голосов
/ 24 марта 2011

Закрытие содержит состояние, которое сохраняется между вызовами внутренней функции. В этом случае он используется, поэтому время ожидания может быть только одно. Если вы хотите использовать несколько тайм-аутов одновременно, вы можете просто написать

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);
...