Проблеми setTimeout / clearTimeout


103

Я намагаюся зробити сторінку, щоб перейти на стартову сторінку після напр. 10 сек бездіяльності (користувач нікуди не натискає). Я використовую jQuery для решти, але набір / очищення в моїй тестовій функції - це чистий JavaScript.

У своєму роздратованості я закінчив щось подібне до цієї функції, за яку я сподівався, що зможу зателефонувати будь-яким клацанням сторінки. Таймер запускається нормально, але не скидається при натисканні. Якщо функція буде викликана 5 разів протягом перших 10 секунд, з'явиться 5 попереджувальних повідомлень ... немає чіткого часу ...

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

Це тому, що таймер є локальною змінною вашої функції.

Спробуйте створити його поза функцією.


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 до входу.


1
Це те, що я шукав пару годин, дякую. Мені було просто цікаво, чи є кращий спосіб для такого результату?
Нікасв

1
@nikasv дроселювання та дебютація
zero_cool

2

Не впевнений, чи це порушує якесь правило хорошої практики кодування, але я зазвичай виходжу з цим:

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

Це запобігає необхідності оголошення таймера поза функцією.

EDIT: це також не оголошує нову змінну при кожному виклику, але завжди переробляє таку саму.

Сподіваюся, це допомагає.


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 спрацьовує, коли він утримується протягом декількох мілісекунд, визначених утримуванням параметра. Параметр 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
    );
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.