135 votes

javascript : pause setTimeout() ;

Si j'ai un délai d'attente actif en cours d'exécution qui a été défini par l'intermédiaire de var t = setTimeout("dosomething()", 5000) ,

Y a-t-il un moyen de faire une pause et de la reprendre ?


Y a-t-il un moyen d'obtenir le temps restant sur le délai d'attente actuel ?
ou dois-je, dans une variable, lorsque le délai d'attente est fixé, stocker l'heure actuelle, puis, lorsque nous faisons une pause, obtenir la différence entre maintenant et après ?

1 votes

Pour ceux qui se posent la question, la mise en pause s'applique par exemple à un div qui doit disparaître dans 5 secondes, à 3 secondes (donc 2 secondes restantes) l'utilisateur passe la souris sur le div, vous mettez en pause le délai d'attente, une fois que l'utilisateur passe la souris sur le div, vous le reprenez, 2 secondes plus tard il disparaît.

299voto

Tim Down Points 124501

Vous pourriez envelopper window.setTimeout comme ceci, qui je pense est similaire à ce que vous suggériez dans la question :

var Timer = function(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();

3 votes

@yckart : Retourné, désolé. C'est un bon ajout, sauf que l'ajout de paramètres supplémentaires à la fonction setTimeout() ne fonctionne pas dans Internet Explorer <= 9.

0 votes

@TimDown Mhh, ok. Mais, qui s'en soucie ? oldIE ? ! :P Et BTW, setTimeout fonctionne même avec arguments en IE lt 9 : fiddle.jshell.net/kx9VU

0 votes

@yckart : IE 8 est encore très présent, malheureusement. Votre jsFiddle ne prouve rien ; vouliez-vous dire quelque chose comme ceci ? jsfiddle.net/adwKX

20voto

Sean Vieira Points 47080

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

1 votes

J'ai changé +new Date() a new Date().getTime() car il est plus rapide : jsperf.com/date-vs-gettime

0 votes

Le meilleur, papi !

10voto

yckart Points 7517

Une version légèrement modifiée de Tim Downs réponse . Cependant, puisque Tim retourné mon édition, je dois répondre à cette question moi-même. Ma solution permet d'utiliser des arguments comme troisième (3, 4, 5...) paramètre et pour effacer la minuterie :

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é, les paramètres supplémentaires ne sont pas disponibles dans l'application IE lt 9 Cependant, j'ai travaillé un peu pour qu'il puisse fonctionner en oldIE aussi.

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;

9voto

RoToRa Points 20081

Non. Vous devez l'annuler ( clearTimeout ), mesurez le temps écoulé depuis que vous l'avez lancé et redémarrez-le avec la nouvelle heure.

7voto

T.J. Crowder Points 285826

"Pause" et "reprise" n'ont pas vraiment de sens dans le contexte de setTimeout qui est un unique chose. Tu pourrais vouloir faire une pause série chaînée de setTimeout Dans ce cas, il suffit de ne pas programmer le prochain appel (et peut-être d'annuler celui qui est en suspens par l'intermédiaire de l'application clearTimeout comme ci-dessous). Mais setTimeout lui-même ne tourne pas en boucle, il n'y a rien à mettre en pause et à reprendre.

Si vous voulez dire setInterval alors non, vous ne pouvez pas la mettre en pause, vous pouvez seulement l'annuler ( clearInterval ), puis le reprogrammer à nouveau. Les détails de tout cela dans le Section Timers de la spécification.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X