JavaScript getTimeout? - PullRequest
       12

JavaScript getTimeout?

17 голосов
/ 24 декабря 2009

Функция window.setTimeout (и связанный с ней setInterval) в Javascript позволяет запланировать выполнение функции в будущем:

id = setTimeout(function, delay);

где «delay» - это количество миллисекунд в будущем, в которое вы хотите вызвать функцию. До истечения этого времени вы можете отменить таймер, используя:

clearTimeout(id);

Что я хочу это обновить таймер. Я хочу иметь возможность продвигать или задерживать таймер, чтобы функция называлась х миллисекундами раньше или позже , чем первоначально планировалось.

Если бы существовал метод getTimeout, вы могли бы сделать что-то вроде:

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

но, насколько я могу судить, нет ничего лучше getTimeout или какого-либо способа обновить существующий таймер.

Есть ли способ получить доступ к списку запланированных сигналов тревоги и изменить их?

Есть ли лучший подход?

спасибо!

Ответы [ 5 ]

14 голосов
/ 24 декабря 2009

Если вы действительно хотите такого рода функциональность, вам нужно написать это самостоятельно.

Вы можете создать оболочку для вызова 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
4 голосов
/ 24 декабря 2009

Я верю, что нет. Лучшим подходом может быть написание собственной оболочки, которая хранит ваши таймеры (func-ref, delay и timestamp). Таким образом, вы можете притвориться, что обновили таймер, очистив его и рассчитав копию с обновленной задержкой.

2 голосов
/ 24 декабря 2009

Другая обертка:

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!
0 голосов
/ 24 декабря 2009

Это может быть не совсем то, что вы хотите, но все равно посмотрите, может быть, вы можете использовать его в своих интересах.

Существует отличное решение, написанное моим бывшим сотрудником, которое может создавать специальные функции-обработчики, которые могут останавливать и запускать тайм-ауты при необходимости. Это наиболее широко используется, когда вам нужно создать небольшую задержку для событий наведения. Например, когда вы хотите скрыть меню при наведении курсора не точно в тот момент, когда мышь покидает его, а через несколько миллисекунд. Но если мышь возвращается, вам нужно отменить тайм-аут.

Решением является функция с именем 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);

P.S. Чтобы это решение работало, вам необходимо расширить объект Function с помощью функции curry, которая автоматически выполняется в Prototype .

0 голосов
/ 24 декабря 2009

Одна возможность может быть такой:

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

Вам решать, как вы строите свои условия или логику. спасибо

...