Probleme mit setTimeout / clearTimeout

103

Ich versuche eine Seite zu erstellen, um zur Startseite zu gelangen, nachdem z. 10 Sekunden Inaktivität (Benutzer klickt nirgendwo hin). Ich benutze jQuery für den Rest, aber das Set / Clear in meiner Testfunktion ist reines Javascript.

In meinem Frust hatte ich so etwas wie diese Funktion, von der ich hoffte, dass ich sie bei jedem Klick auf die Seite aufrufen konnte. Der Timer startet einwandfrei, wird jedoch nicht mit einem Klick zurückgesetzt. Wenn die Funktion innerhalb der ersten 10 Sekunden fünfmal aufgerufen wird, werden 5 Warnungen angezeigt ... kein clearTimeout ...

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

Hat jemand ein paar Codezeilen, die den Trick machen? - Bei jedem Klick stoppen, zurücksetzen und den Timer starten. - Wenn der Timer z. 10sec etwas tun.

Tillebeck
quelle

Antworten:

225

Sie müssen timer außerhalb der Funktion deklarieren . Andernfalls erhalten Sie bei jedem Funktionsaufruf eine brandneue Variable.

var timer;
function endAndStartTimer() {
  window.clearTimeout(timer);
  //var millisecBeforeRedirect = 10000; 
  timer = window.setTimeout(function(){alert('Hello!');},10000); 
}
Spitze
quelle
plus 1 eins, da in diesem Fall die Variable gelöscht werden muss, die das timeOut verdeckt, bevor das Timeout aufgerufen wird, um zu vermeiden, dass es zweimal aufgerufen wird
Diego Favero
46

Das Problem ist, dass die timerVariable lokal ist und ihr Wert nach jedem Funktionsaufruf verloren geht.

Sie müssen es beibehalten, Sie können es außerhalb der Funktion platzieren oder wenn Sie die Variable nicht als global verfügbar machen möchten, können Sie sie in einem Abschluss speichern , z.

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

Das liegt daran, dass der Timer eine lokale Variable für Ihre Funktion ist.

Versuchen Sie es außerhalb der Funktion zu erstellen.

Arclight
quelle
6

Eine Möglichkeit, dies zu verwenden, um zu reagieren:

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

  }
}

Hilfreich, wenn Sie eine API erst aufrufen möchten, nachdem der Benutzer beispielsweise die Eingabe beendet hat. Die userTimeout-Funktion kann über onKeyUp an eine Eingabe gebunden werden.

zero_cool
quelle
1
Das ist es, wonach ich ein paar Stunden gesucht habe, danke. Ich habe mich nur gefragt, ob es einen besseren Weg für ein solches Ergebnis gibt.
Nikasv
1
@nikasv Drosselung und Entprellen sind zwei Alternativen: medium.com/@_jh3y/…
zero_cool
2

Ich bin mir nicht sicher, ob dies gegen eine bewährte Codierungsregel verstößt, aber ich komme normalerweise mit dieser heraus:

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

Dies verhindert, dass der Timer für die Funktion deklariert werden muss.

BEARBEITEN: Dies deklariert auch nicht bei jedem Aufruf eine neue Variable, sondern recycelt immer dieselbe.

Hoffe das hilft.

Clamiax
quelle
0

Das funktioniert gut. Es ist ein Manager, den ich für Hold-Events gemacht habe. Hat Ereignisse zum Halten und zum Loslassen.

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

Der Elementparameter ist derjenige, den Sie halten. Der func-Parameter wird ausgelöst, wenn er einige Millisekunden lang hält, die durch den Parameter hold angegeben werden. Der Parameter clearfunc ist optional. Wenn er angegeben wird, wird er ausgelöst, wenn der Benutzer das Element loslässt oder verlässt. Sie können auch einige Problemumgehungen durchführen, um die gewünschten Funktionen zu erhalten. Genießen! :) :)

Kino Bacaltos
quelle
0

Praktisches Beispiel Verwenden von Jquery für ein Dropdown-Menü! Wenn Sie mit der Maus über #IconLoggedinUxExternal fahren, wird div # ExternalMenuLogin angezeigt, und es wird eine Zeitüberschreitung festgelegt, um div # ExternalMenuLogin auszublenden

Wenn Sie mit der Maus über div # ExternalMenuLogin fahren, wird das Timeout abgebrochen. Wenn Sie mit der Maus auf div # ExternalMenuLogin fahren, wird das Zeitlimit festgelegt.

Hier geht es immer darum, clearTimeout aufzurufen, bevor das Timeout festgelegt wird, um doppelte Anrufe zu vermeiden

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
    );
});
Diego Favero
quelle