web-dev-qa-db-fra.com

javascript: pause setTimeout ();

Si un délai d'attente actif est défini via var t = setTimeout("dosomething()", 5000),

Est-il possible de faire une pause et de le reprendre?



110
Hailwood

Vous pourriez envelopper window.setTimeout comme ceci, ce qui est semblable à ce que vous suggérez dans la question:

function Timer(callback, delay) {
    var timerId, start, remaining = delay;

    this.pause = function() {
        window.clearTimeout(timerId);
        remaining -= Date.now() - start;
    };

    this.resume = function() {
        start = Date.now();
        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();
241
Tim Down

Quelque chose comme ça devrait faire l'affaire.

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 };
}
16
Sean Vieira

Non, vous devrez l'annuler (clearTimeout), mesurer le temps écoulé depuis le début et le redémarrer à la nouvelle heure.

9
RoToRa

Une version légèrement modifiée de Tim Downs answer . Cependant, depuis Tim annulé mon édition, je dois y répondre moi-même. Ma solution permet d'utiliser extra arguments comme troisième paramètre (3, 4, 5 ...) et d'effacer le chronomètre:

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

Comme Tim l'a mentionné, des paramètres supplémentaires ne sont pas disponibles dans IE lt 9, Mais j'ai un peu travaillé pour que cela fonctionne également dans oldIE.

Utilisation: 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;
7
yckart

"Pause" et "reprise" n'ont pas vraiment de sens dans le contexte de setTimeout, qui est une chose unique . Voulez-vous dire setInterval? Si c'est le cas, non, vous ne pouvez pas le suspendre, vous pouvez seulement l'annuler (clearInterval), puis le reprogrammer. Détails de tous ceux-ci dans le section Timers de la spéc.

// 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);
6
T.J. Crowder

Le délai d'attente était assez facile à trouver, mais l'intervalle était un peu plus compliqué.

Je suis venu avec les deux classes suivantes pour résoudre ces problèmes:

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

Ceux-ci peuvent être implémentés comme tels:

var pt_hey = new PauseableTimeout(function(){
    alert("hello");
}, 2000);

window.setTimeout(function(){
    pt_hey.pause();
}, 1000);

window.setTimeout("pt_hey.start()", 2000);

Cet exemple définira un délai d'attente (pt_hey) qui est programmé pour alerter, "hé" après deux secondes. Un autre délai d'attente met pt_hey en pause après une seconde. Un troisième délai d'attente reprend pt_hey après deux secondes. pt_hey s'exécute pendant une seconde, s'interrompt une seconde, puis reprend son exécution. pt_hey se déclenche après trois secondes.

Maintenant pour les intervalles les plus difficiles

var pi_hey = new PauseableInterval(function(){
    console.log("hello world");
}, 2000);

window.setTimeout("pi_hey.pause()", 5000);

window.setTimeout("pi_hey.resume()", 6000);

Cet exemple définit un intervalle en pause (pi_hey) pour écrire "hello world" dans la console toutes les deux secondes. Un délai d'attente met pi_hey en pause après cinq secondes. Un autre délai d'attente reprend pi_hey après six secondes. Donc pi_hey va se déclencher deux fois, courir pendant une seconde, faire une pause pendant une seconde, courir pendant une seconde, puis continuer à se déclencher toutes les 2 secondes.

AUTRES FONCTIONS

  • clearTimeout () et clearInterval ()

    pt_hey.clearTimeout(); et pi_hey.clearInterval(); permettent de supprimer facilement les délais et les intervalles.

  • getTimeLeft ()

    pt_hey.getTimeLeft(); et pi_hey.getTimeLeft(); renverront combien de millisecondes jusqu'à ce que le prochain déclencheur se produise.

6
TheCrzyMan

/relancer

Version ES6 utilisant du sucre syntactique de classe y

(légèrement modifié: ajouté 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))
<!doctype html>
<html>
<head>
  <title>Traditional HTML Document. ZZz...</title>
  <style type="text/css">
    .wow { color: blue; font-family: Tahoma, sans-serif; font-size: 1em; }
  </style>
</head>
<body>
  <h1>DOM &amp; JavaScript</h1>

  <div id="change-me">I'm going to repaint my life, wait and see.</div>

  <button id="timer-start">Start!</button>
  <button id="timer-pause">Pause!</button>
  <button id="timer-resume">Resume!</button>
</body>
</html>
2
jeremiah.trein

Je devais calculer le temps écoulé et le temps restant pour afficher une barre de progression. Ce n’était pas facile d’utiliser la réponse acceptée. 'setInterval' est meilleur que 'setTimeout' pour cette tâche. J'ai donc créé cette classe Timer que vous pouvez utiliser dans n'importe quel projet.

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

Vous pouvez regarder dans clearTimeout ()

ou pause en fonction d'une variable globale définie lorsqu'une condition donnée est atteinte. Comme si on appuyait sur un bouton.

  <button onclick="myBool = true" > pauseTimeout </button>

  <script>
  var myBool = false;

  var t = setTimeout(function() {if (!mybool) {dosomething()}}, 5000);
  </script>
1
John Hartsock

Vous pouvez également l'implémenter avec des événements.

Au lieu de calculer le décalage horaire, vous démarrez et arrêtez l'écoute d'un événement 'tick' qui continue à s'exécuter en arrière-plan:

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

};
1
meleyal

Je devais être capable de mettre en pause setTimeout () pour une fonctionnalité semblable à un diaporama.

Voici ma propre implémentation d'une minuterie en pause. Il intègre les commentaires vus sur la réponse de Tim Down, tels que meilleure pause (commentaire du noyau) et une forme de prototypage (commentaire de 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 */

Exemple:

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

Pour tester le code, utilisez timer.resume() et timer.pause() plusieurs fois et vérifiez le temps qu'il vous reste. (Assurez-vous que votre console est ouverte.)

Utiliser cet objet à la place de setTimeout () est aussi simple que de remplacer timerID = setTimeout( mycallback, 1000) par timer = new Timer( mycallback, 1000 ). Alors timer.pause() et timer.resume() sont à votre disposition.

1
Fabien Snauwaert

Si vous utilisez jquery de toute façon, consultez le plugin $. DoTimeout . Cette opération représente une amélioration considérable par rapport à setTimeout. Elle vous permet notamment de suivre vos délais d’expiration avec un identifiant de chaîne unique que vous spécifiez et qui ne change pas à chaque fois que vous le définissez, et d’implémenter des fonctions simples d’annulation, de boucle plus. Un de mes plugins jquery les plus utilisés.

Malheureusement, il ne prend pas en charge les fonctions de pause/reprise prêtes à l'emploi. Pour cela, vous devez envelopper ou étendre $ .doTimeout, probablement de la même manière que la réponse acceptée.

1
Ben Roberts

Je pense que vous ne trouverez rien de mieux que clearTimeout . Quoi qu'il en soit, vous pouvez toujours planifier un autre délai plus tard, au lieu de le "reprendre".

0
Nikita Rybak