javascript: pause setTimeout ();

Se ho un timeout attivo che è stato impostato tramite var t = setTimeout("dosomething()", 5000) ,

C’è comunque da mettere in pausa e riprenderlo?


C’è un modo per ottenere il tempo rimanente sul timeout corrente?
o devo inserire una variabile, quando è impostato il timeout, memorizzare l’ora corrente, poi ci fermiamo, otteniamo la differenza tra ora e poi?

Potresti window.setTimeout questo modo, che penso sia simile a quello che stavi suggerendo nella domanda:

 function Timer(callback, delay) { var timerId, start, remaining = delay; this.pause = function() { window.clearTimeout(timerId); remaining -= new Date() - start; }; this.resume = function() { start = new Date(); window.clearTimeout(timerId); timerId = window.setTimeout(callback, remaining); }; this.resume(); } var timer = new Timer(function() { alert("Done!"); }, 1000); timer.pause(); // Do some stuff... timer.resume(); 

Qualcosa come questo dovrebbe fare il trucco.

 function Timer(fn, countdown) { var ident, complete = false; function _time_diff(date1, date2) { return date2 ? date2 - date1 : new Date().getTime() - date1; } function cancel() { clearTimeout(ident); } function pause() { clearTimeout(ident); total_time_run = _time_diff(start_time); complete = total_time_run >= countdown; } function resume() { ident = complete ? -1 : setTimeout(fn, countdown - total_time_run); } var start_time = new Date().getTime(); ident = setTimeout(fn, countdown); return { cancel: cancel, pause: pause, resume: resume }; } 

No. Avrai bisogno di cancellarlo ( clearTimeout ), misurare il tempo da quando lo hai avviato e riavviarlo con la nuova ora.

Una versione leggermente modificata della risposta di Tim Downs. Tuttavia, poiché Tim ha ripristinato la mia modifica, devo rispondere io stesso. La mia soluzione rende ansible utilizzare arguments extra come terzo (3, 4, 5 …) parametro e per cancellare il timer:

 function Timer(callback, delay) { var args = arguments, self = this, timer, start; this.clear = function () { clearTimeout(timer); }; this.pause = function () { this.clear(); delay -= new Date() - start; }; this.resume = function () { start = new Date(); timer = setTimeout(function () { callback.apply(self, Array.prototype.slice.call(args, 2, args.length)); }, delay); }; this.resume(); } 

Come menzionato da Tim, i parametri extra non sono disponibili in IE lt 9 , tuttavia ho lavorato un po ‘in modo che funzionasse anche in oldIE .

Uso: new Timer(Function, Number, arg1, arg2, arg3...)

 function callback(foo, bar) { console.log(foo); // "foo" console.log(bar); // "bar" } var timer = new Timer(callback, 1000, "foo", "bar"); timer.pause(); document.onclick = timer.resume; 

“Pausa” e “ripresa” non hanno molto senso nel contesto di setTimeout , che è una cosa una tantum . Intendi setInterval ? Se è così, no, non puoi metterlo in pausa, puoi solo cancellarlo ( clearInterval ) e poi riprogrammarlo di nuovo. Dettagli di tutti questi nella sezione Timers della specifica.

 // Setting var t = setInterval(doSomething, 1000); // Pausing (which is really stopping) clearInterval(t); t = 0; // Resuming (which is really just setting again) t = setInterval(doSomething, 1000); 

Il Timeout è stato abbastanza facile da trovare una soluzione, ma l’intervallo è stato un po ‘più complicato.

Ho trovato le seguenti due classi per risolvere questo problema:

 function PauseableTimeout(func, delay){ this.func = func; var _now = new Date().getTime(); this.triggerTime = _now + delay; this.t = window.setTimeout(this.func,delay); this.paused_timeLeft = 0; this.getTimeLeft = function(){ var now = new Date(); return this.triggerTime - now; } this.pause = function(){ this.paused_timeLeft = this.getTimeLeft(); window.clearTimeout(this.t); this.t = null; } this.resume = function(){ if (this.t == null){ this.t = window.setTimeout(this.func, this.paused_timeLeft); } } this.clearTimeout = function(){ window.clearTimeout(this.t);} } function PauseableInterval(func, delay){ this.func = func; this.delay = delay; this.triggerSetAt = new Date().getTime(); this.triggerTime = this.triggerSetAt + this.delay; this.i = window.setInterval(this.func, this.delay); this.t_restart = null; this.paused_timeLeft = 0; this.getTimeLeft = function(){ var now = new Date(); return this.delay - ((now - this.triggerSetAt) % this.delay); } this.pause = function(){ this.paused_timeLeft = this.getTimeLeft(); window.clearInterval(this.i); this.i = null; } this.restart = function(sender){ sender.i = window.setInterval(sender.func, sender.delay); } this.resume = function(){ if (this.i == null){ this.i = window.setTimeout(this.restart, this.paused_timeLeft, this); } } this.clearInterval = function(){ window.clearInterval(this.i);} } 

Questi possono essere implementati come tali:

 var pt_hey = new PauseableTimeout(function(){ alert("hello"); }, 2000); window.setTimeout(function(){ pt_hey.pause(); }, 1000); window.setTimeout("pt_hey.start()", 2000); 

Questo esempio imposterà un Timeout pausabile (pt_hey) che è pianificato per avvisare, “hey” dopo due secondi. Un altro timeout fa una pausa di pt_hey dopo un secondo. Un terzo Timeout riprende pt_hey dopo due secondi. pt_hey viene eseguito per un secondo, si interrompe per un secondo, quindi riprende a funzionare. pt_hey si triggers dopo tre secondi.

Ora per gli intervalli più difficili

 var pi_hey = new PauseableInterval(function(){ console.log("hello world"); }, 2000); window.setTimeout("pi_hey.pause()", 5000); window.setTimeout("pi_hey.resume()", 6000); 

Questo esempio imposta un intervallo pausabile (pi_hey) per scrivere “ciao mondo” nella console ogni due secondi. Un timeout si interrompe dopo cinque secondi. Un altro timeout riprende pi_hey dopo sei secondi. Quindi pi_hey si innescherà due volte, correrà per un secondo, metterà in pausa per un secondo, correrà per un secondo e poi continuerà ad triggersrsi ogni 2 secondi.

ALTRE FUNZIONI

  • clearTimeout () e clearInterval ()

    pt_hey.clearTimeout(); e pi_hey.clearInterval(); serve come un modo semplice per cancellare i timeout e gli intervalli.

  • getTimeLeft ()

    pt_hey.getTimeLeft(); e pi_hey.getTimeLeft(); restituirà quanti millisecondi fino al prossimo trigger è pianificato.

Avevo bisogno di calcolare il tempo trascorso e il tempo rimanente per mostrare una barra di avanzamento. Non è stato facile usare la risposta accettata. ‘setInterval’ è migliore di ‘setTimeout’ per questa attività. Quindi, ho creato questa class Timer che puoi usare in qualsiasi progetto.

https://jsfiddle.net/ashraffayad/t0mmv853/

 'use strict'; //Constructor var Timer = function(cb, delay) { this.cb = cb; this.delay = delay; this.elapsed = 0; this.remaining = this.delay - self.elapsed; }; console.log(Timer); Timer.prototype = function() { var _start = function(x, y) { var self = this; if (self.elapsed < self.delay) { clearInterval(self.interval); self.interval = setInterval(function() { self.elapsed += 50; self.remaining = self.delay - self.elapsed; console.log('elapsed: ' + self.elapsed, 'remaining: ' + self.remaining, 'delay: ' + self.delay); if (self.elapsed >= self.delay) { clearInterval(self.interval); self.cb(); } }, 50); } }, _pause = function() { var self = this; clearInterval(self.interval); }, _restart = function() { var self = this; self.elapsed = 0; console.log(self); clearInterval(self.interval); self.start(); }; //public member definitions return { start: _start, pause: _pause, restart: _restart }; }(); // - - - - - - - - how to use this class var restartBtn = document.getElementById('restart'); var pauseBtn = document.getElementById('pause'); var startBtn = document.getElementById('start'); var timer = new Timer(function() { console.log('Done!'); }, 2000); restartBtn.addEventListener('click', function(e) { timer.restart(); }); pauseBtn.addEventListener('click', function(e) { timer.pause(); }); startBtn.addEventListener('click', function(e) { timer.start(); }); 

Non penso che troverai nulla di meglio di clearTimeout . Ad ogni modo, puoi sempre programmare un altro timeout in seguito, invece di “riprenderlo”.

Puoi guardare clearTimeout ()

o mettere in pausa a seconda di una variabile globale che viene impostata quando viene raggiunta una determinata condizione. Come un pulsante è premuto.

    

Puoi anche implementarlo con eventi.

Invece di calcolare la differenza di orario, si avvia e si interrompe l’ascolto di un evento “tick” che continua a essere eseguito in background:

 var Slideshow = { _create: function(){ this.timer = window.setInterval(function(){ $(window).trigger('timer:tick'); }, 8000); }, play: function(){ $(window).bind('timer:tick', function(){ // stuff }); }, pause: function(){ $(window).unbind('timer:tick'); } }; 

Se stai usando jquery comunque, controlla il plugin $ .doTimeout . Questa cosa è un enorme miglioramento rispetto a setTimeout, che ti permette di tenere traccia dei tuoi timeout con un id a stringa singola che specifichi e che non cambia ogni volta che lo imposti, e implementa cancellazioni, cicli di polling e debouncing facili e Di Più. Uno dei miei plugin jquery più usati.

Sfortunatamente, non supporta pause / resume out of the box. Per questo, è necessario avvolgere o estendere $ .doTimeout, presumibilmente in modo simile alla risposta accettata.

Dovevo essere in grado di mettere in pausa setTimeout () per la funzione simile a una presentazione.

Ecco la mia implementazione di un timer pausabile. Integra i commenti visti sulla risposta di Tim Down, come una pausa migliore (il commento del kernel) e una forma di prototipazione (il commento di Umur Gedik).

 function Timer( callback, delay ) { /** Get access to this object by value **/ var self = this; /********************* PROPERTIES *********************/ this.delay = delay; this.callback = callback; this.starttime;// = ; this.timerID = null; /********************* METHODS *********************/ /** * Pause */ this.pause = function() { /** If the timer has already been paused, return **/ if ( self.timerID == null ) { console.log( 'Timer has been paused already.' ); return; } /** Pause the timer **/ window.clearTimeout( self.timerID ); self.timerID = null; // this is how we keep track of the timer having beem cleared /** Calculate the new delay for when we'll resume **/ self.delay = self.starttime + self.delay - new Date().getTime(); console.log( 'Paused the timer. Time left:', self.delay ); } /** * Resume */ this.resume = function() { self.starttime = new Date().getTime(); self.timerID = window.setTimeout( self.callback, self.delay ); console.log( 'Resuming the timer. Time left:', self.delay ); } /********************* CONSTRUCTOR METHOD *********************/ /** * Private constructor * Not a language construct. * Mind var to keep the function private and () to execute it right away. */ var __construct = function() { self.starttime = new Date().getTime(); self.timerID = window.setTimeout( self.callback, self.delay ) }(); /* END __construct */ } /* END Timer */ 

Esempio:

 var timer = new Timer( function(){ console.log( 'hey! this is a timer!' ); }, 10000 ); timer.pause(); 

Per testare il codice, utilizzare timer.resume() e timer.pause() alcune volte e controllare quanto tempo è rimasto. (Assicurati che la tua console sia aperta.)

Usare questo object al posto di setTimeout () è facile come sostituire timerID = setTimeout( mycallback, 1000) con timer = new Timer( mycallback, 1000 ) . Quindi timer.pause() e timer.resume() sono a tua disposizione.

/ rilanciare

Versione ES6 utilizzando zucchero sintattico di class 💋

(leggermente modificato: aggiunto start ())

 class Timer { constructor(callback, delay) { this.callback = callback this.remainingTime = delay this.startTime this.timerId } pause() { clearTimeout(this.timerId) this.remainingTime -= new Date() - this.startTime } resume() { this.startTime = new Date() clearTimeout(this.timerId) this.timerId = setTimeout(this.callback, this.remainingTime) } start() { this.timerId = setTimeout(this.callback, this.remainingTime) } } // supporting code const pauseButton = document.getElementById('timer-pause') const resumeButton = document.getElementById('timer-resume') const startButton = document.getElementById('timer-start') const timer = new Timer(() => { console.log('called'); document.getElementById('change-me').classList.add('wow') }, 3000) pauseButton.addEventListener('click', timer.pause.bind(timer)) resumeButton.addEventListener('click', timer.resume.bind(timer)) startButton.addEventListener('click', timer.start.bind(timer)) 
    Traditional HTML Document. ZZz...    

DOM & JavaScript

I'm going to repaint my life, wait and see.

Se hai diverse div da hide, potresti usare un setInterval e un numero di cicli per fare come in:

 
1
2
3
4