setTimeout / clearTimeout проблемы

103

Я пытаюсь сделать так, чтобы страница переходила на стартовую, например, после. 10 секунд бездействия (пользователь никуда не нажимает). В остальном я использую jQuery, но set / clear в моей тестовой функции - это чистый javascript.

В моем разочаровании я получил что-то вроде этой функции, которую я надеялся вызвать при любом щелчке на странице. Таймер запускается нормально, но не сбрасывается одним щелчком мыши. Если функция вызывается 5 раз в течение первых 10 секунд, появится 5 предупреждений ... no clearTimeout ...

function endAndStartTimer() {
    window.clearTimeout(timer);
    var timer;
    //var millisecBeforeRedirect = 10000; 
    timer = window.setTimeout(function(){alert('Hello!');},10000); 
}

У кого-нибудь есть несколько строк кода, которые помогут? - при любом нажатии остановка, сброс и запуск таймера. - Когда таймер срабатывает, например. 10сек сделай что-нибудь.

Тиллебек
источник

Ответы:

226

Вам нужно объявить timer вне функции. В противном случае вы получаете новую переменную при каждом вызове функции.

var timer;
function endAndStartTimer() {
  window.clearTimeout(timer);
  //var millisecBeforeRedirect = 10000; 
  timer = window.setTimeout(function(){alert('Hello!');},10000); 
}
Заостренный
источник
плюс 1 единица, потому что в этом случае необходимо очистить переменную, которая закрывает timeOut, перед вызовом тайм-аута, чтобы избежать ее повторного вызова
Диего Фаверо
46

Проблема в том, что timerпеременная локальная, и ее значение теряется после каждого вызова функции.

Вам нужно сохранить его, вы можете поместить его вне функции, или, если вы не хотите, чтобы переменная была глобальной, вы можете сохранить ее в закрытии , например:

var endAndStartTimer = (function () {
  var timer; // variable persisted here
  return function () {
    window.clearTimeout(timer);
    //var millisecBeforeRedirect = 10000; 
    timer = window.setTimeout(function(){alert('Hello!');},10000); 
  };
})();
Кристиан К. Сальвадо
источник
15

Это потому, что таймер - это локальная переменная вашей функции.

Попробуйте создать его вне функции.

arclight
источник
6

Способ использовать это в реакции:

class Timeout extends Component {
  constructor(props){
    super(props)

    this.state = {
      timeout: null
    }

  }

  userTimeout(){
    const { timeout } = this.state;
    clearTimeout(timeout);
    this.setState({
      timeout: setTimeout(() => {this.callAPI()}, 250)
    })

  }
}

Полезно, если вы хотите, например, вызывать API только после того, как пользователь перестал печатать. Функция userTimeout может быть привязана к входу через onKeyUp.

zero_cool
источник
1
Это то, что я искал пару часов, спасибо. Мне просто было интересно, есть ли лучший способ добиться такого результата?
Nikasv
1
@nikasv дросселирования и дребезг две альтернативы: medium.com/@_jh3y/...
zero_cool
2

Не уверен, что это нарушает какое-то правило кодирования хорошей практики, но обычно я прихожу с таким:

if(typeof __t == 'undefined')
        __t = 0;
clearTimeout(__t);
__t = setTimeout(callback, 1000);

Это избавляет от необходимости объявлять таймер вне функции.

РЕДАКТИРОВАТЬ: это также не объявляет новую переменную при каждом вызове, но всегда перерабатывает то же самое.

Надеюсь это поможет.

Clamiax
источник
0

Это хорошо работает. Это менеджер, который я сделал для обработки удерживаемых событий. Есть события для удержания и для того, чтобы отпустить.

function onUserHold(element, func, hold, clearfunc) {
    //var holdTime = 0;
    var holdTimeout;

    element.addEventListener('mousedown', function(e) {
        holdTimeout = setTimeout(function() {
            func();
            clearTimeout(holdTimeout);
            holdTime = 0;
        }, hold);
        //alert('UU');
    });

    element.addEventListener('mouseup', clearTime);
    element.addEventListener('mouseout', clearTime);

    function clearTime() {
        clearTimeout(holdTimeout);
        holdTime = 0;
        if(clearfunc) {
            clearfunc();
        }
    }
}

Параметр элемента - это тот, который вы держите. Параметр func срабатывает, когда он удерживается в течение количества миллисекунд, указанного параметром hold. Параметр clearfunc является необязательным, и если он задан, он будет активирован, если пользователь отпустит или покинет элемент. Вы также можете выполнить некоторые обходные действия, чтобы получить нужные функции. Наслаждайтесь! :)

Кино Бакальто
источник
0

Практический пример Использование JQuery для выпадающего меню! При наведении указателя мыши на #IconLoggedinUxExternal показывает div # ExternalMenuLogin и устанавливает время ожидания, чтобы скрыть div # ExternalMenuLogin

При наведении указателя мыши на div # ExternalMenuLogin время ожидания отменяется. При наведении указателя мыши на div # ExternalMenuLogin он устанавливает тайм-аут.

Дело здесь всегда в том, чтобы вызывать clearTimeout перед установкой тайм-аута, чтобы избежать двойных вызовов

var ExternalMenuLoginTO;
$('#IconLoggedinUxExternal').on('mouseover mouseenter', function () {

    clearTimeout( ExternalMenuLoginTO )
    $("#ExternalMenuLogin").show()
});

$('#IconLoggedinUxExternal').on('mouseleave mouseout', function () {

    clearTimeout( ExternalMenuLoginTO )    
    ExternalMenuLoginTO = setTimeout(
        function () {

            $("#ExternalMenuLogin").hide()

        }
        ,1000
    );
    $("#ExternalMenuLogin").show()
});

$('#ExternalMenuLogin').on('mouseover mouseenter', function () {

    clearTimeout( ExternalMenuLoginTO )
});
$('#ExternalMenuLogin').on('mouseleave mouseout', function () {

    clearTimeout( ExternalMenuLoginTO )
    ExternalMenuLoginTO = setTimeout(
        function () {

            $("#ExternalMenuLogin").hide()

        }
        ,500
    );
});
Диего Фаверо
источник