web-dev-qa-db-fra.com

Qu'advient-il de setTimeout lorsque l'ordinateur se met en veille?

Dans un navigateur Web moderne, supposons que je fasse une setTimeout pendant 10 minutes (à midi) et 5 minutes plus tard, en mettant l'ordinateur en veille, que devrait-il se passer lorsque le système se réveillera? Que se passe-t-il s'il se réveille avant que les 10 minutes ne soient écoulées (à 12h09) ou beaucoup plus tard (à 16h00)?

La raison pour laquelle je pose la question est parce que j'aimerais demander un nouveau jeton d'authentification toutes les 10 minutes, et je ne suis pas sûr que le navigateur agisse correctement et demande immédiatement un nouveau jeton s'il se réveille après une longue période. temps. 

Clarifications : Je ne veux pas utiliser de cookies - J'essaie de créer un service Web ici; et oui, le serveur rejettera les anciens et invalides jetons.

51
Sudhir Jonathan

Pour autant que j'ai testé, il s'arrête et reprend après le réveil de l'ordinateur. Je suppose que cela signifie que pour une session dépendant de setTimeout/Interval, le compteur est activé à partir du moment où l'ordinateur s'est endormi. 

Je ne pense pas que vous devriez vous fier à l'exactitude de setTimeout/Interval pour les tâches critiques. Pour Google Chrome I récemment découvert , tout délai/intervalle (inférieur à 1 s) sera ralenti une fois par seconde si l'onglet où il est activé perd le focus. 

En dehors de cela, la précision des délais/intervalles dépend des autres fonctions en cours d'exécution, etc. En bref: ce n'est pas très précis.

Donc, en utilisant l'intervalle et les délais, comparer l'heure à une heure de début dans la fonction lancée par celle-ci vous donnerait une meilleure précision. Maintenant, si vous commencez à 12h00, l'ordinateur se met en veille et se réveille à 16h13 environ, en comparant 16h13 à 12h00, vous êtes certain de devoir renouveler le jeton. Vous trouverez un exemple d'utilisation de la comparaison de temps ici

42
KooiInc

Comparez la date/heure actuelle avec la date et l'heure du chargement de la page, comme suit:

//Force refresh after x minutes.
var initialTime = new Date();
var checkSessionTimeout = function () {
    var minutes = Math.abs((initialTime - new Date()) / 1000 / 60);
    if (minutes > 20) {
        setInterval(function () { location.href = 'Audit.aspx' }, 5000)
    } 
};
setInterval(checkSessionTimeout, 1000);
4
Ben

Le comportement est basé à la fois sur le navigateur et sur le système d'exploitation. Le système d'exploitation gère le sommeil et les applications individuelles n'en tiennent souvent pas compte.

Ce qui va probablement arriver, c’est que le système d’exploitation reviendra avec le même temps que celui qui s’est écoulé à la minuterie. L'autre possibilité est qu'il ne tirera pas du tout.

S'il s'agit vraiment d'une préoccupation, vous voudrez probablement être mieux protégé que guérir et stocker un horodatage du moment où le jeton a été initialisé et utiliser setInterval pour le vérifier périodiquement (par exemple deux fois par minute).

Cependant, la sécurité ne devrait pas être simplement une affaire de client. Assurez-vous que votre serveur génère une erreur si un ancien jeton/non valide est utilisé et que Ajax se comporte correctement en réponse.

[modifier] Je suis d'accord avec l'autre message selon lequel il pourrait être déclenché immédiatement au prochain tick. Le blog de Resig est très bon.

3
Andrew Curioso

Voici mon code: 

<!doctype html>
<html>

<body>
<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 120000)"/>

</body>
<script>


</script>
</html>

J'ai pris trois scénarios qui pourraient répondre à la question. 

Scénario 1: À 00 seconde, cliquez sur le bouton "Démarrer la minuterie". Au bout de 25 secondes, l'ordinateur s'endort . À 1min 40 secondes, réveillez l'ordinateur . À 2 minutes, l'alerte est affichée.

Scénario 2: À 00 seconde, cliquez sur le bouton "Démarrer la minuterie". À 26 secondes, l'ordinateur s'endort ... à 3 minutes, je le réveille. L'alerte est affichée.

Scénario 3: Celui-ci est vraiment stupéfiant.

<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 600000)"/>

À 00 secondes, je clique sur le bouton "Démarrer la minuterie". À environ 1 minute 30 secondes, l’ordinateur est en mode Veille prolongée (mon ordinateur met une minute pour lancer le mode Veille prolongée)

À 8 minutes, j'allume l'ordinateur portable. À 10 minutes exactement, l'alerte apparaît. 

PS: This is my first ever comment on Stack Exchange. I prefer to execute code and view results rather than infer from theory.
2
DannyBoi

Comportement des temporisateurs JavaScript (setTimeout) dans plusieurs scénarios.

  1. Lorsque le thread est libre et que le délai d'attente est écoulé: le minuteur est déclenché immédiatement après le délai d'attente. Il peut y avoir une certaine imprécision d’environ 0 à 5 ms (scénario typique).
  2. Lorsque le thread est très occupé (boucle énorme) suffisamment longtemps pour que le délai du minuteur soit dépassé: le minuteur sera exécuté immédiatement après la libération du thread.
  3. Lorsqu'il y a une alerte: Même comportement que 2.
  4. Lorsque le fil est en pause parce que notre ordinateur portable s'est endormi: j'ai vu plusieurs choses. Mais le plus commun est l'inexactitude totale et ignore le temps passé pendant le sommeil.

Étant donné que les minuteries en JavaScript sont basées sur des ticks de la CPU et que celle-ci est en veille, la minuterie est complètement mise en pause et reprend comme "puisque rien ne se serait passé".

2
José Cabo

Basé sur la réponse de Ben, j'ai créé l'util suivant. Vous pouvez modifier la durée d’échantillonnage, mais je l’utilise exactement comme cela pour rafraîchir les jetons:

const absoluteSetInterval = (handler, timeout) => {
  let baseTime = Date.now();
  const callHandler = () => {
    if (Date.now() - baseTime > timeout) {
      baseTime = Date.now();
      handler();
    }
  };
  return window.setInterval(callHandler, 1000);
};

const absoluteClearInterval = (handle) => window.clearInterval(handle);
0
Erez Cohen