problemas de setTimeout / clearTimeout

103

Intento hacer una página para ir a la página de inicio después de, por ejemplo. 10 segundos de inactividad (el usuario no hace clic en ningún lado). Utilizo jQuery para el resto, pero el set / clear en mi función de prueba son javascript puro.

En mi frustración, terminé con algo como esta función a la que esperaba poder llamar con cualquier clic en la página. El temporizador comienza bien, pero no se reinicia con un clic. Si se llama a la función 5 veces en los primeros 10 segundos, aparecerán 5 alertas ... no clearTimeout ...

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

¿Alguien tiene algunas líneas de código que funcionarán? - en cualquier clic de detener, reiniciar e iniciar el temporizador. - Cuando llega el temporizador, por ejemplo. 10 segundos haz algo.

Tillebeck
fuente

Respuestas:

226

Necesitas declarar timer fuera de la función. De lo contrario, obtiene una variable nueva en cada invocación de función.

var timer;
function endAndStartTimer() {
  window.clearTimeout(timer);
  //var millisecBeforeRedirect = 10000; 
  timer = window.setTimeout(function(){alert('Hello!');},10000); 
}
Puntiagudo
fuente
más 1 uno porque es necesario, en este caso, despejar la variable que enmascara el timeOut antes de llamar al time out, así evitando que sea invocado dos veces
Diego Favero
46

El problema es que la timervariable es local y su valor se pierde después de cada llamada de función.

Debe conservarlo, puede ponerlo fuera de la función, o si no desea exponer la variable como global, puede almacenarlo en un cierre , por ejemplo:

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

Eso es porque el temporizador es una variable local de su función.

Intente crearlo fuera de la función.

arclight
fuente
6

Una forma de usar esto en reaccionar:

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

  }
}

Útil si solo desea llamar a una API después de que el usuario haya dejado de escribir, por ejemplo. La función userTimeout podría vincularse a través de onKeyUp a una entrada.

zero_cool
fuente
1
Esto es lo que he estado buscando durante un par de horas, gracias. Me preguntaba si hay una mejor manera de que suceda este tipo de resultado.
Nikasv
1
@nikasv estrangulamiento y eliminación de rebotes son dos alternativas: medium.com/@_jh3y/…
zero_cool
2

No estoy seguro de si esto viola alguna regla de codificación de buenas prácticas, pero generalmente salgo con esta:

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

Esto evita la necesidad de declarar el temporizador fuera de la función.

EDITAR: esto tampoco declara una nueva variable en cada invocación, pero siempre recicla lo mismo.

Espero que esto ayude.

clamiax
fuente
0

Esto funciona bien. Es un gerente que he creado para manejar eventos. Tiene eventos para retener y para cuando los dejas ir.

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

El parámetro del elemento es el que tienes. El parámetro func se activa cuando se mantiene durante una cantidad de milisegundos especificada por el parámetro hold. El parámetro clearfunc es opcional y, si se proporciona, se activará si el usuario suelta o abandona el elemento. También puede hacer algunas soluciones para obtener las funciones que desea. ¡Disfrutar! :)

Kino Bacaltos
fuente
0

Ejemplo práctico ¡Usando Jquery para un menú desplegable! Al pasar el mouse sobre #IconLoggedinUxExternal, muestra div # ExternalMenuLogin y establece el tiempo de espera para ocultar el div # ExternalMenuLogin

Al pasar el mouse sobre div # ExternalMenuLogin, cancela el tiempo de espera. Con el mouse en div # ExternalMenuLogin, establece el tiempo de espera.

El punto aquí es siempre invocar clearTimeout antes de establecer el tiempo de espera, por lo tanto, evitar llamadas dobles

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
fuente