Was passiert mit setTimeout, wenn der Computer in den Ruhezustand wechselt?

75

Angenommen, ich mache in einem modernen Webbrowser eine setTimeout10-minütige (um 12:00 Uhr) und 5 Minuten später den Computer in den Ruhezustand. Was soll passieren, wenn das System wieder aufwacht? Was passiert, wenn es aufwacht, bevor die 10 Minuten abgelaufen sind (um 12:09 Uhr) oder viel später (um 16:00 Uhr)?

Der Grund, den ich frage, ist, dass ich alle 10 Minuten ein neues Authentifizierungstoken anfordern möchte und ich nicht sicher bin, ob der Browser das Richtige tut und sofort ein neues Token anfordert, wenn es nach langer Zeit aufwacht Zeit.

Präzisierungen : Ich wan't nicht zu verwenden Cookies - Ich versuche hier einen Web - Service zu bauen; und ja, der Server lehnt alte und ungültige Token ab.

Sudhir Jonathan
quelle
1
Wäre es nicht besser, ein Cookie zu setzen, das zu einem bestimmten Zeitpunkt ablaufen kann, da Javascript clientseitig ist?
Daybreaker
stackoverflow.com/questions/3824754/… schlägt vor, wie Andrew antwortete, dass es nicht funktionieren wird.
Sysyphus
@daybreaker, Sicher sind Cookies möglich, aber ich versuche eine service-basierte App zu erstellen. Gleiche Dienste gelten für die Web-App, das iPhone und die Android-App.
Sudhir Jonathan

Antworten:

61

Soweit ich getestet habe, stoppt es einfach und wird fortgesetzt, nachdem der Computer aufgewacht ist. Ich nehme an, das bedeutet für eine Sitzung, abhängig vom setTimeout/IntervalZähler, ab dem Zeitpunkt, an dem der Computer eingeschlafen ist.

Ich denke nicht, dass Sie sich auf die Genauigkeit setTimeout/Intervalzeitkritischer Dinge verlassen sollten. Bei Google Chrome habe ich kürzlich festgestellt, dass jedes Timeout / Intervall (das kürzer als 1s ist) auf einmal pro Sekunde verlangsamt wird, wenn der Tab, auf dem es aktiviert ist, den Fokus verliert.

Abgesehen davon hängt die Genauigkeit von Zeitüberschreitungen / Intervallen von anderen laufenden Funktionen usw. ab. Kurz gesagt: Sie ist nicht sehr genau.

Wenn Sie also Intervalle und Zeitüberschreitungen verwenden und die Zeit mit einer Startzeit innerhalb der von ihr gestarteten Funktion vergleichen, erhalten Sie eine bessere Genauigkeit. Wenn Sie jetzt um 12:00 Uhr beginnen, geht der Computer in den Ruhezustand und wacht um 16:13 Uhr auf. Wenn Sie 16:13 Uhr gegen 12:00 Uhr prüfen, sind Sie sicher, dass Sie den Token erneuern müssen. Ein Beispiel für die Verwendung des Zeitvergleichs finden Sie hier

KooiInc
quelle
1
Dies entspricht auch meiner Erfahrung.
JWL
Ich habe gerade einen Schnelltest dafür erstellt. FF 30 und Chrome 35 lösen das lange Zeitlimit in angemessener Weise aus, sobald der Computer wieder aufgenommen wird. IE 10 lädt die Seite neu. Fiddle @ jsfiddle.net/Pegleg3941/8uhy8
EpicVoyage
the counter ticks on from the time the computer fell asleep.<- auch meine Erfahrung.
Mahn
1
Ab 2017 (Chrome 61) hat sich dieses Verhalten, den Zähler vom Einschlafen abzuhalten, nicht geändert.
Erez Cohen
4
Ich denke, dies könnte klarer formuliert werden: Wenn der Computer das setInterval / setTimeout aufweckt, ist nicht bekannt, dass eine Zeit vergangen ist.
cdosborn
8

Vergleichen Sie die aktuelle Datums- und Uhrzeitangabe mit der Datums- und Uhrzeitangabe beim Laden der Seite wie folgt:

//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);
Ben
quelle
Dies ist eine großartige Lösung. Funktioniert sehr gut für mich - danke.
BeesonBison
In meinem Fall muss ich nur dann ein neues Token erhalten, wenn der Benutzer aktiv ist und in der letzten Stunde nicht inaktiv war. Also vom Server-Token mit Ablauf nach 1 Stunde, aber vorher muss ich ein neues Token erhalten und localStorage aktualisieren. Wenn der Benutzer inaktiv ist, zeigen Sie die Nachricht "Sitzung abgelaufen" an, andernfalls erhalten Sie stillschweigend ein neues Token
CyberAbhay,
Was ist der Grund für das innere setInterval ()? Warum 5 Sekunden?
Robsch
7

Hier ist mein Code:

<!doctype html>
<html>

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

</body>
<script>


</script>
</html>

Ich habe drei Szenarien genommen, die die Frage beantworten könnten.

Szenario 1: Klicken Sie um 00 Sekunden auf die Schaltfläche "Timer starten". Nach 25 Sekunden schläft der Computer ein. Nach 1 Minute 40 Sekunden Computer aufwecken. Nach 2 Minuten wird eine Warnung angezeigt.

Szenario 2: Klicken Sie um 00 Sekunden auf die Schaltfläche "Timer starten". Nach 26 Sekunden schläft der Computer ein. Nach 3 Minuten wecke ich den Computer. Der Alarm wird angezeigt.

Szenario 3: Dieser ist wirklich erstaunlich.

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

Um 00 Sekunden klicke ich auf die Schaltfläche 'Timer starten'. Nach ca. 1 Minute und 30 Sekunden befindet sich der Computer im Ruhezustand (mein PC benötigt eine Minute, um den Ruhezustand einzuleiten).

Nach 8 Minuten schalte ich den Laptop ein. Genau nach 10 Minuten erscheint die Warnung.

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

Das Verhalten basiert sowohl auf dem Browser als auch auf dem Betriebssystem. Das Betriebssystem behandelt den Ruhezustand und einzelne Apps berücksichtigen dies häufig nicht.

Was höchstwahrscheinlich passieren wird, ist, dass das Betriebssystem mit der gleichen Zeit auf dem Timer zurückkehrt, die beim Herunterfahren verbleibt. Die andere Möglichkeit ist, dass es überhaupt nicht feuert.

Wenn es wirklich ein Problem ist, möchten Sie wahrscheinlich besser auf Nummer sicher gehen und einen Zeitstempel für die Initialisierung des Tokens speichern und setIntervalihn regelmäßig überprüfen (z. B. zweimal pro Minute).

Sicherheit sollte jedoch nicht nur eine clientseitige Angelegenheit sein. Stellen Sie sicher, dass Ihr Server einen Fehler auslöst, wenn ein altes / ungültiges Token verwendet wird, und dass sich der Ajax als Antwort angemessen verhält.

[Bearbeiten] Ich stimme dem anderen Beitrag zu, dass er beim nächsten Tick sofort ausgelöst werden könnte. Resigs Blogpost ist sehr gut.

Andrew Curioso
quelle
Der Server wird ein älteres Token ablehnen ... Ich versuche, dem Client keine unnötigen Fehler
Sudhir Jonathan
Ich habe tatsächlich darüber nachgedacht, wie sich meine eigenen Apps in diesem Fall verhalten werden ... das ist wirklich eine gute Frage. Ich möchte mich fast bei meiner Bank anmelden und versuchen, zu sehen, wie sie sich verhalten.
Andrew Curioso
Sie verwenden wahrscheinlich einen Cookie mit einem Zeitstempel. Ich versuche hier mit kochfreien Diensten zu arbeiten, daher die Frage.
Sudhir Jonathan
In Bezug auf Andrews Bearbeitung: Es wird möglicherweise sofort beim Aufwecken ausgelöst, dies hängt jedoch vom Browser ab.
EpicVoyage
IE 10 lädt beispielsweise die Seite neu.
EpicVoyage
4

Basierend auf Bens Antwort habe ich den folgenden Util erstellt. Sie können die Abtastdauer anpassen, ich verwende sie jedoch wie folgt für die Token-Aktualisierung:

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);
Erez Cohen
quelle
2

Verhalten von JavaScript-Timern (setTimeout) in mehreren Szenarien.

  1. Wenn der Thread frei ist und das Timeout ausgelöst wird: Der Timer wird unmittelbar nach dem Timeout ausgelöst. Es kann eine gewisse Ungenauigkeit von etwa 0 bis 5 ms aufweisen (typisches Szenario).
  2. Wenn der Thread sehr beschäftigt ist (große Schleife), um das Timer-Timeout zu überschreiten: Der Timer wird sofort ausgeführt, nachdem der Thread freigegeben wurde.
  3. Wenn eine Warnung vorliegt: Gleiches Verhalten wie 2.
  4. Wenn der Thread angehalten wird, weil unser Laptop eingeschlafen ist: Ich habe verschiedene Dinge gesehen. Am häufigsten ist jedoch die völlige Ungenauigkeit und das Ignorieren der Zeit, die während des Schlafens verbracht wird.

Da Timer in JavaScript auf CPU-Ticks basieren und die CPU im Ruhezustand ist, wird der Timer vollständig angehalten und als "da nichts passiert wäre" fortgesetzt.

José Cabo
quelle
-2

In John Resigs Blog sollen die Timer "Wanduhr" verwenden. Ich glaube, dass die Ereignisse sofort nach der Wiederaufnahme der Maschine ausgelöst werden, da setTimeout () nicht garantiert, dass eine Ausführung ein bestimmter Zeitpunkt ist, sondern so bald wie möglich nach dem angegebenen Intervall. Ich habe es jedoch nicht selbst überprüft.

Evgeny Shadchnev
quelle
10
Du hättest es überprüfen sollen - es funktioniert nicht so und deine Schlussfolgerung basierend auf JRs Blog ist sehr locker. Es folgt definitiv nicht der Wanduhr auf einem System, auf dem ich getestet habe.
JWL
1
FWIW, die Spezifikation sagt dies: "Warten Sie, bis das mit dem Methodenkontext verknüpfte Dokument für eine weitere Zeitüberschreitung von Millisekunden ( nicht unbedingt nacheinander ) vollständig aktiv war ." Das bedeutet, dass der Timer angehalten werden kann, während der Computer schläft.
Geon