problemi di setTimeout / clearTimeout


103

Provo a creare una pagina per andare alla pagina iniziale dopo ad es. 10sec di inattività (l'utente non fa clic da nessuna parte). Uso jQuery per il resto, ma il set / clear nella mia funzione di test è javascript puro.

Nella mia frustrazione sono finito con qualcosa di simile a questa funzione che speravo di poter chiamare a qualsiasi clic sulla pagina. Il timer si avvia correttamente, ma non viene ripristinato con un clic. Se la funzione viene chiamata 5 volte entro i primi 10 secondi, verranno visualizzati 5 avvisi ... no clearTimeout ...

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

Qualcuno ha delle righe di codice che faranno il trucco? - ad ogni clic ferma, reimposta e avvia il timer. - Quando il timer colpisce ad es. 10sec fa qualcosa.

Risposte:


226

Devi dichiarare timer al di fuori della funzione. Altrimenti, ottieni una nuova variabile su ogni chiamata di funzione.

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

più 1 perché occorre, in questo caso, azzerare la variabile che incappuccia il timeOut prima di chiamare il time out, così facendo, evitando che venga richiamato due volte
Diego Favero

46

Il problema è che la timervariabile è locale e il suo valore viene perso dopo ogni chiamata di funzione.

Devi renderlo persistente, puoi metterlo fuori dalla funzione, o se non vuoi esporre la variabile come globale, puoi memorizzarla in una chiusura , ad esempio:

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

15

Questo perché il timer è una variabile locale della tua funzione.

Prova a crearlo al di fuori della funzione.


6

Un modo per usarlo in React:

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

  }
}

Utile se desideri chiamare un'API solo dopo che l'utente ha smesso di digitare, ad esempio. La funzione userTimeout potrebbe essere associata tramite onKeyUp a un input.


1
Questo è quello che stavo cercando da un paio d'ore, grazie. Mi stavo solo chiedendo se esiste un modo migliore per ottenere questo tipo di risultato?
Nikasv

1
@nikasv throttling e debouncing sono due alternative: medium.com/@_jh3y/…
zero_cool

2

Non sono sicuro che ciò violi alcune regole di codifica di buone pratiche, ma di solito esco con questo:

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

Ciò evita la necessità di dichiarare il timer fuori dalla funzione.

EDIT: anche questo non dichiara una nuova variabile ad ogni invocazione, ma ricicla sempre la stessa.

Spero che questo ti aiuti.


0

Funziona bene. È un manager che ho creato per gestire gli eventi di attesa. Ha eventi da tenere e per quando lasci andare.

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

Il parametro dell'elemento è quello che tieni premuto. Il parametro func si attiva quando rimane per un numero di millisecondi specificato dal parametro hold. Il parametro clearfunc è opzionale e, se fornito, verrà attivato se l'utente lascia andare o abbandona l'elemento. Puoi anche fare alcune soluzioni per ottenere le funzionalità che desideri. Godere! :)


0

Esempio pratico Utilizzo di Jquery per un menu a discesa! Al passaggio del mouse su #IconLoggedinUxExternal mostra il div # ExternalMenuLogin e imposta il timeout per nascondere il div # ExternalMenuLogin

Al passaggio del mouse su div # ExternalMenuLogin annulla il timeout. All'uscita del mouse su div # ExternalMenuLogin imposta il timeout.

Il punto qui è sempre invocare clearTimeout prima di impostare il timeout, in questo modo, evitando doppie chiamate

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
    );
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.