Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

278
Visualizações
Iniciar y detener un temporizador con setTimeout recursivo

Estoy tratando de iniciar y detener un temporizador con un setTimeout recursivo, ya que setInterval no se ajusta a mis necesidades. Cuando el usuario presiona iniciar, el temporizador comienza a contar.

1...2...3...4..5...1...2...3..4...5...1..2...3..4. ..5...

Y cuando el usuario presiona detener, debería detener este bucle de temporizador. Si presiono iniciar nuevamente, cambiando el estado del botón (variable de flujo), el temporizador debería hacer lo mismo nuevamente (1..2..3..4..5..1..2...3. .4...5..)

Pensé que la forma de hacerlo sería esta.

 const ref = useRef(null); useEffect(() => { if (!stream) { ref.current=setTimeout(repeatingFunc, 1000); } else { clearTimeout(ref.current); } }, [stream]); function repeatingFunc() { console.log("It's been 5 seconds. Execute the function again."); setTimeout(repeatingFunc, 5000); }

¿Qué estoy haciendo mal?

El temporizador no se detiene. ¡Continúa incluso si presiono detener! (¡cambiando el valor del estado de la transmisión!)

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

Puede definir un temporizador personalizado como este:

 function CustomTimer(func) { this.id = -1; this.func = func; this.start = function (interval) { this.stop(); if (this.func) { var t = this; this.id = setTimeout(function () { t.func.call(t) }, interval || 1000); } } this.stop = function () { if (this.id >= 0) { clearTimeout(this.id); this.id = -1; } } }

Y úsalo:

 var myTimer = new CustomTimer(function () { console.log("It's been 5 seconds. Execute the function again."); this.start(5000); }); myTimer.start(5000);

Puedes cambiar la función a ejecutar en cualquier momento y también el intervalo. Por ejemplo: ejecute un evento de inicio en 1 segundo y luego, 5 veces cada 5 segundos haga otra cosa:

 var secondFunc = function () { console.log("It's been 5 seconds. Execute the function again."); if (++this.count < 5) this.start(5000); } var myTimer = new CustomTimer(function () { console.log("First event at 1 second"); this.count = 0; this.func = secondFunc; this.start(5000); }); myTimer.start(1000);
about 4 years ago · Juan Pablo Isaza Relatório

0

La razón por la que el temporizador no se detiene es porque solo almacena el ID de tiempo de espera de la llamada setTimeout inicial. Cuando se llama a repeatingFunc , se registra otra devolución de llamada setTimeout , que tiene una nueva ID de tiempo de espera.

Entonces, cuando intenta borrar el tiempo de espera usando clearTimeout(ref.current) , está pasando una ID de tiempo de espera desactualizada.

Dado que ya se ha llamado al registro anterior setTimeout , ya no necesita almacenar la ID anterior y simplemente puede reemplazarla por la nueva.

 const ref = useRef(null); useEffect(() => { if (!stream) { ref.current = setTimeout(repeatingFunc, 1000); } else { clearTimeout(ref.current); } }, [stream]); function repeatingFunc() { console.log("It's been 5 seconds. Execute the function again."); ref.current = setTimeout(repeatingFunc, 5000); // ^^^^^^^^^^^^ update timeout ID after registering a new timeout }

Tenga en cuenta que el alcance de repeatingFunc se fija en un punto en el tiempo en el que inicialmente llama a setTimeout(repeatingFunc, 1000) , lo que significa que cosas como estados y propiedades pueden contener valores obsoletos. Esto podría o no convertirse en un problema dependiendo de su contexto.


También es posible que desee agregar una función de limpieza useEffect que borre el tiempo de espera en el desmontaje del componente. De lo contrario, su ciclo continúa, incluso cuando el componente ya no está montado.

 useEffect(() => { if (!stream) { ref.current = setTimeout(repeatingFunc, 1000); } return () => clearTimeout(ref.current); }, [stream]);

Suponiendo que la stream es un valor booleano ( true / false ), lo anterior borrará el tiempo de espera actual cada vez que se cambie el valor de la stream o cuando se desmonte el componente.

Cuando la stream cambia de true a false , se llamará a la función de limpieza y se borrará el tiempo de espera.

Cuando la stream cambia de false a true , también se llama a la función de limpieza, pero no funciona porque la referencia actual ref.current no está registrada. Entonces se establece un nuevo tiempo de espera.

Pasar una ID no válida a clearTimeout() no hace nada en silencio; no se lanza ninguna excepción.

Ver: MDN - clearTimeout()

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda