setTimeout / clearTimeout sorunları


103

Örn. Sonra başlangıç ​​sayfasına gitmek için bir sayfa yapmaya çalışıyorum. 10 saniye hareketsizlik (kullanıcı hiçbir yere tıklamaz). Geri kalanı için jQuery kullanıyorum ama test fonksiyonumdaki set / clear tamamen javascript.

Hayal kırıklığımla, sayfadaki herhangi bir tıklamayla arayabileceğimi umduğum bu işlev gibi bir şeyle sonuçlandım. Zamanlayıcı iyi başlar, ancak bir tıklamayla sıfırlanmaz. İşlev ilk 10 saniye içinde 5 kez çağrılırsa, 5 uyarı görünecektir ... clearTimeout yok ...

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

Hile yapacak bazı satır kodlara sahip olan var mı? - herhangi bir tıklama ile durdurma, sıfırlama ve zamanlayıcıyı başlatma. - Zamanlayıcı ör. 10sn bir şeyler yapın.

Yanıtlar:


226

Fonksiyonun timer dışında beyan etmeniz gerekir . Aksi takdirde, her işlev çağrısında yepyeni bir değişken elde edersiniz.

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

artı 1 bir, çünkü bu durumda, zaman aşımını çağırmadan önce timeOut'u kapatan değişkeni temizlemek gerekir, öyle ki, iki kez çalıştırılmaktan kaçınır
Diego Favero

46

Sorun, timerdeğişkenin yerel olması ve her işlev çağrısından sonra değerinin kaybolmasıdır.

Kalıcı olmalısınız, onu işlevin dışına koyabilirsiniz veya değişkeni global olarak göstermek istemiyorsanız, bir kapanışta saklayabilirsiniz , örneğin:

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

15

Bunun nedeni, zamanlayıcının işleviniz için yerel bir değişken olmasıdır.

Bunu işlevin dışında oluşturmayı deneyin.


6

Bunu tepki olarak kullanmanın bir yolu:

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)
    })

  }
}

Örneğin, kullanıcı yazmayı durdurduktan sonra bir API çağırmak isterseniz faydalıdır. UserTimeout işlevi, onKeyUp aracılığıyla bir girişe bağlanabilir.


1
Birkaç saattir aradığım şey bu, teşekkürler. Bu tür bir sonucun gerçekleşmesi için daha iyi bir yol olup olmadığını merak ediyordum.
Nikasv

1
@nikasv azaltma ve hata bildirme iki alternatiftir: medium.com/@_jh3y/…
zero_cool

2

Bunun bazı iyi uygulama kodlama kurallarını ihlal edip etmediğinden emin değilim, ancak genellikle bununla çıkarım:

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

Bu, zamanlayıcıyı işlevin dışında ilan etme ihtiyacını önler.

DÜZENLEME: bu ayrıca her çağrıda yeni bir değişken bildirmez, ancak her zaman aynı şeyi geri dönüştürür.

Bu yardımcı olur umarım.


0

Bu iyi çalışıyor. Bekletme olaylarını halletmek için yaptığım bir yönetici. Bekletilecek ve bıraktığınız zamanlar için etkinlikler var.

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();
        }
    }
}

Eleman parametresi, tuttuğunuz parametredir. Func parametresi, parametre bekletme tarafından belirtilen sayıda milisaniye tuttuğunda tetiklenir. Clearfunc parametresi isteğe bağlıdır ve verilirse, kullanıcı öğeden çıkmasına izin verirse veya bırakırsa ateşlenir. İstediğiniz özellikleri elde etmek için bazı geçici çözümler de yapabilirsiniz. Zevk almak! :)


0

Pratik örnek Bir açılır menü için Jquery kullanma! #IconLoggedinUxExternal üzerinde fareyle üzerine gelindiğinde div # ExternalMenuLogin'i gösterir ve div # ExternalMenuLogin'i gizlemek için zaman aşımını ayarlayın

Div # ExternalMenuLogin üzerinde fareyle üzerine gelindiğinde, zaman aşımını iptal eder. Div # ExternalMenuLogin üzerinde fareyi bıraktığınızda zaman aşımını ayarlar.

Buradaki nokta, zaman aşımını ayarlamadan önce her zaman clearTimeout'u çağırmaktır, böylece çift aramalardan kaçınarak

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
    );
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.