working sirve react que para not loop javascript timeout settimeout

javascript - sirve - encontrar el tiempo que queda en un setTimeout()?



settimeout not working (10)

EDITAR: en realidad creo que hice una mejor: https://stackoverflow.com/a/36389263/2378102

Escribí esta función y la uso mucho:

function timer(callback, delay) { var id, started, remaining = delay, running this.start = function() { running = true started = new Date() id = setTimeout(callback, remaining) } this.pause = function() { running = false clearTimeout(id) remaining -= new Date() - started } this.getTimeLeft = function() { if (running) { this.pause() this.start() } return remaining } this.getStateRunning = function() { return running } this.start() }

Hacer un temporizador:

a = new timer(function() { // What ever }, 3000)

Entonces, si quieres que te quede el tiempo justo, hazlo:

a.getTimeLeft()

Estoy escribiendo un Javascript que interactúa con el código de la biblioteca que no soy de mi propiedad y no puedo (razonablemente) cambiar. Crea tiempos de espera de Javascript utilizados para mostrar la siguiente pregunta en una serie de preguntas de tiempo limitado. Este no es un código real porque está ofuscado más allá de toda esperanza. Esto es lo que la biblioteca está haciendo:

.... // setup a timeout to go to the next question based on user-supplied time var t = questionTime * 1000 test.currentTimeout = setTimeout( showNextQuestion(questions[i+1]), t );

Quiero poner una barra de progreso en pantalla que se llene hacia questionTime * 1000 al interrogar el temporizador creado por setTimeout . El único problema es que parece que no hay forma de hacer esto. ¿Hay una función getTimeout que me falta? La única información sobre los tiempos de espera de Javascript que puedo encontrar está relacionada solo con la creación a través de setTimeout( function, time) y eliminación a través de clearTimeout( id ) .

Estoy buscando una función que devuelva el tiempo restante antes de que se agote el tiempo de espera o el tiempo transcurrido después de que se haya llamado a un tiempo de espera. Mi código de barras de progreso se ve así:

var timeleft = getTimeout( test.currentTimeout ); // I don''t know how to do this var $bar = $(''.control .bar''); while ( timeleft > 1 ) { $bar.width(timeleft / test.defaultQuestionTime * 1000); }

tl; dr: ¿Cómo encuentro el tiempo restante antes de un javascript setTimeout ()?

Aquí está la solución que estoy usando ahora. Pasé por la sección de la biblioteca que está a cargo de las pruebas y descifré el código (terrible y en contra de mis permisos).

// setup a timeout to go to the next question based on user-supplied time var t = questionTime * 1000 test.currentTimeout = mySetTimeout( showNextQuestion(questions[i+1]), t );

y aquí está mi código:

// wrapper for setTimeout function mySetTimeout( func, timeout ) { timeouts[ n = setTimeout( func, timeout ) ] = { start: new Date().getTime(), end: new Date().getTime() + timeout t: timeout } return n; }

Esto funciona bastante bien en cualquier navegador que no sea IE 6. Incluso el iPhone original, donde esperaba que las cosas se volvieran asíncronas.


Esta es quizás una forma aún mejor de hacerlo, además, no necesitará cambiar el código que ya ha escrito:

var getTimeout = (function() { // IIFE var _setTimeout = setTimeout, // Reference to the original setTimeout map = {}; // Map of all timeouts with their start date and delay setTimeout = function(callback, delay) { // Modify setTimeout var id = _setTimeout(callback, delay); // Run the original, and store the id map[id] = [Date.now(), delay]; // Store the start date and delay return id; // Return the id }; return function(id) { // The actual getTimeLeft function var m = map[id]; // Find the timeout in map // If there was no timeout with that id, return NaN, otherwise, return the time left clamped to 0 return m ? Math.max(m[1] - Date.now() + m[0], 0) : NaN; } })();

... Y mimetizado:

var getTimeout=function(){var e=setTimeout,b={};setTimeout=function(a,c){var d=e(a,c);b[d]=[Date.now(),c];return d};return function(a){return(a=b[a])?Math.max(a[1]-Date.now()+a[0],0):NaN}}();


La pregunta ya ha sido respondida pero agregaré mi parte. Simplemente se me ocurrió.

Use setTimeout en la recursion siguiente manera:

var count = -1; function beginTimer() { console.log("Counting 20 seconds"); count++; if(count <20) { console.log(20-count+"seconds left"); setTimeout(beginTimer,2000); } else { endTimer(); } } function endTimer() { console.log("Time is finished"); }

Supongo que el código es auto explicativo


Las pilas de eventos de Javascript no operan cómo piensas.

Cuando se crea un evento de tiempo de espera, se agrega a la cola de eventos, pero otros eventos pueden tener prioridad mientras se está disparando ese evento, retrasar el tiempo de ejecución y posponer el tiempo de ejecución.

Ejemplo: crea un tiempo de espera con un retraso de 10 segundos para alertar algo a la pantalla. Se agregará a la pila de eventos y se ejecutará después de que se activen todos los eventos actuales (lo que ocasiona cierta demora). Luego, cuando se procesa el tiempo de espera, el navegador continúa capturando otros eventos y los agrega a la pila, lo que causa más retrasos en el procesamiento. Si el usuario hace clic, o escribe mucho ctrl +, sus eventos tienen prioridad sobre la pila actual. Sus 10 segundos pueden convertirse en 15 segundos o más.

Dicho esto, hay muchas maneras de simular cuánto tiempo ha pasado. Una forma es ejecutar un setInterval justo después de agregar el setTimeout a la pila.

Ejemplo: Realice un tiempo de ajuste con un retraso de 10 segundos (almacene ese retraso en un global). A continuación, realice un setInterval que se ejecuta cada segundo para restar 1 del retraso y dar salida a la demora restante. Debido a la forma en que la pila de eventos puede influir en el tiempo real (descrito anteriormente), esto aún no será preciso, pero da un conteo.

En resumen, no hay una forma real de obtener el tiempo restante. Solo hay formas de intentar y transmitir una estimación al usuario.


No, pero puede tener su propio setTimeout / setInterval para la animación en su función.

Diga que su pregunta es así:

function myQuestion() { // animate the progress bar for 1 sec animate( "progressbar", 1000 ); // do the question stuff // ... }

Y su animación será manejada por estas 2 funciones:

function interpolate( start, end, pos ) { return start + ( pos * (end - start) ); } function animate( dom, interval, delay ) { interval = interval || 1000; delay = delay || 10; var start = Number(new Date()); if ( typeof dom === "string" ) { dom = document.getElementById( dom ); } function step() { var now = Number(new Date()), elapsed = now - start, pos = elapsed / interval, value = ~~interpolate( 0, 500, pos ); // 0-500px (progress bar) dom.style.width = value + "px"; if ( elapsed < interval ) setTimeout( step, delay ); } setTimeout( step, delay ); }


Revisa este:

class Timer { constructor(fun,delay) { this.timer=setTimeout(fun, delay) this.stamp=new Date() } get(){return ((this.timer._idleTimeout - (new Date-this.stamp))/1000) } clear(){return (this.stamp=null, clearTimeout(this.timer))} }

Hacer un temporizador:

let smtg = new Timer(()=>{do()}, 3000})

Sigue siendo:

smth.get()

Borrar tiempo de espera

smth.clear()


Si alguien mira hacia atrás en esto. He salido con un gestor de tiempo de espera e intervalo que puede obtener el tiempo restante en un tiempo de espera o intervalo, así como también hacer otras cosas. Lo agregaré para que sea más ingenioso y preciso, pero parece funcionar bastante bien (aunque tengo algunas ideas más para hacerlo aún más preciso):

https://github.com/vhmth/Tock


Si no puede modificar el código de la biblioteca, deberá redefinir setTimeout para que se ajuste a sus propósitos. Aquí hay un ejemplo de lo que podrías hacer:

(function () { var nativeSetTimeout = window.setTimeout; window.bindTimeout = function (listener, interval) { function setTimeout(code, delay) { var elapsed = 0, h; h = window.setInterval(function () { elapsed += interval; if (elapsed < delay) { listener(delay - elapsed); } else { window.clearInterval(h); } }, interval); return nativeSetTimeout(code, delay); } window.setTimeout = setTimeout; setTimeout._native = nativeSetTimeout; }; }()); window.bindTimeout(function (t) {console.log(t + "ms remaining");}, 100); window.setTimeout(function () {console.log("All done.");}, 1000);

Esto no es código de producción, pero debería ponerlo en el camino correcto. Tenga en cuenta que solo puede enlazar un oyente por timeout. No he hecho pruebas exhaustivas con esto, pero funciona en Firebug.

Una solución más robusta usaría la misma técnica de ajuste de setTimeout, pero en su lugar usaría un mapa del timeoutId devuelto a los oyentes para manejar múltiples oyentes por timeout. También podría considerar envolver clearTimeout para que pueda desconectar su oyente si se agota el tiempo de espera.


Solo para el registro, hay una manera de obtener el tiempo restante en node.js:

var timeout = setTimeout(function() {}, 3600 * 1000); setInterval(function() { console.log(''Time left: ''+getTimeLeft(timeout)+''s''); }, 2000); function getTimeLeft(timeout) { return Math.ceil((timeout._idleStart + timeout._idleTimeout - Date.now()) / 1000); }

Huellas dactilares:

$ node test.js Time left: 3599s Time left: 3597s Time left: 3595s Time left: 3593s

Esto no parece funcionar en Firefox, pero como node.js es javascript, pensé que esta observación podría ser útil para las personas que buscan la solución de nodo.


(function(){ window.activeCountdowns = []; window.setCountdown = function (code, delay, callback, interval) { var timeout = delay; var timeoutId = setTimeout(function(){ clearCountdown(timeoutId); return code(); }, delay); window.activeCountdowns.push(timeoutId); setTimeout(function countdown(){ var key = window.activeCountdowns.indexOf(timeoutId); if (key < 0) return; timeout -= interval; setTimeout(countdown, interval); return callback(timeout); }, interval); return timeoutId; }; window.clearCountdown = function (timeoutId) { clearTimeout(timeoutId); var key = window.activeCountdowns.indexOf(timeoutId); if (key < 0) return; window.activeCountdowns.splice(key, 1); }; })(); //example var t = setCountdown(function () { console.log(''done''); }, 15000, function (i) { console.log(i / 1000); }, 1000);