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.