остановить settimeout в рекурсивной функции - PullRequest
13 голосов
/ 15 июня 2009

моя проблема в том, что я не могу остановить таймер.

У меня был этот метод для установки таймаута с этого форума. Предполагается хранить идентификатор в глобальной переменной. Случайно я обнаружил, что он все еще работает после того, как я спрятал "mydiv".

Мне также нужно знать сейчас, создает ли рекурсивная функция несколько экземпляров или только один для тайм-аутов. Потому что сначала я подумал, что он каждый раз перезаписывает "var mytimer". Теперь я не уверен в этом.

Каков был бы надежный способ остановить таймер ??

var updatetimer= function () {
//do stuff
        setTimeout(function (){updatetimer();}, 10000);

}//end function


//this should start and stop the timer
$("#mybutton").click(function(e) { 
         e.preventDefault();
         if($('#mydiv').is(':visible')){
                   $('#mydiv').fadeOut('normal');
             clearTimeout(updatetimer);

        }else{
                   $('#mydiv').fadeIn('normal');
                   updatetimer();
               }
});

спасибо, Ричард

Ответы [ 7 ]

20 голосов
/ 15 июня 2009

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

Кроме того, анонимная функция в setTimeout великолепна, , если вы хотите запустить встроенную логику, изменить значение 'this' внутри функции или передать параметры в функцию . Если вы просто хотите вызвать функцию, достаточно передать имя функции в качестве первого параметра.

var timer = null; 

var updatetimer = function () {
    //do stuff

    // By the way, can just pass in the function name instead of an anonymous
    // function unless if you want to pass parameters or change the value of 'this'
    timer = setTimeout(updatetimer, 10000);
};

//this should start and stop the timer
$("#mybutton").click(function(e) { 
     e.preventDefault();
     if($('#mydiv').is(':visible')){
        $('#mydiv').fadeOut('normal');
        clearTimeout(timer);  // Since the timeout is assigned to a variable, we can successfully clear it now

    } else{
        $('#mydiv').fadeIn('normal');
        updatetimer();
   }
});
7 голосов
/ 15 июня 2009

Я думаю, вы неправильно поняли 'setTimeout' и 'clearTimeout'.

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

foo = setTimeout(function, time);

, затем позвоните

clearTimeout(foo);

если вы хотите отменить таймер.

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

2 голосов
/ 15 июня 2009

Как написано, mytimer - это функция, которая никогда не имеет значения идентификатора тайм-аута, поэтому ваш оператор clearTimeout ничего не даст.

Я не вижу здесь никакой рекурсии, но вам нужно сохранить значение setTimeout возвращает вас, и если вам нужно связать это с несколькими потенциальными событиями, вам нужно сохранить его для ключа значение, которое вы можете найти - возможно, что-то вроде идентификатора элемента?

1 голос
/ 14 декабря 2018

Это простой псевдокод для управления и преобразования рекурсивных функций setTimeout.

    const myVar = setTimeout(function myIdentifier() {

    // some code

    if (condition) {
        clearTimeout(myIdentifier)
    } else {
        setTimeout(myIdentifier, delay); //delay is a value in ms.
    }

}, delay);
1 голос
/ 11 сентября 2015

Вы не можете остановить все созданные функции, в том числе преобразовать функцию в setInterval (представлять ту же логику, что и ваша рекурсивная функция) и остановить ее:

// recursive
var timer= function () {
// do stuff
  setTimeout(function (){timer();}, 10000);
}

Та же логика с использованием setInterval:

 // same logic executing stuff in 10 seconds loop
 var timer = setInterval(function(){// do stuff}, 10000)

Перестань:

 clearInterval(timer);
0 голосов
/ 21 октября 2013

(функция () {

$('#my_div').css('background-color', 'red');
$('#my_div').hover(function(){
var id=setTimeout(function() {
    $('#my_div').css('background-color', 'green');
}, 2000);

var id=setTimeout(function() {
    $('#my_div').css('background-color', 'blue');
}, 4000);
var id=setTimeout(function() {
    $('#my_div').css('background-color', 'pink');
}, 6000);

    })

$("#my_div").click(function(){  
        clearTimeout(id);

        })

}) ();

0 голосов
/ 15 июня 2009

Как отмечалось выше, основная причина, по которой этот код не работает, заключается в том, что вы неправильно передаете в вызов clearTimeout - вам нужно сохранить возвращаемое значение вызова setTimeout, который вы делаете в updateFunction и передайте this в clearTimeout вместо самой ссылки на функцию.

В качестве второго предложения по улучшению - всякий раз, когда у вас есть то, что вы называете функцией рекурсивного тайм-аута, вам будет лучше использовать метод setInterval, который выполняет функцию через регулярные промежутки времени до отмены. Это позволит добиться того же, что вы пытаетесь сделать с помощью метода updateFunction, но он чище, так как вам нужно всего лишь включить логику «делать вещи» в отложенную функцию, и она, вероятно, будет более производительной, поскольку вы этого не сделаете создавая вложенные замыкания. Кроме того, это правильный способ сделать это, который должен что-то значить, верно? : -)

...