In unserer Arbeit denken viele Leute an die beiden Funktionen setTimeout() und setInterval(), wenn sie über den Timer in Javascript sprechen, aber sie wissen nichts über den Timer Was ist das Prinzip? In diesem Artikel werden das Funktionsprinzip und der Unterschied der Timer-Funktion aus der Perspektive der Ereignisschleife (Event Loop) analysiert!
setTimeout()
MDN definiert setTimeout
als:
Nach der angegebenen Verzögerungszeit eine Funktion aufrufen oder ein Codefragment ausführen.
Syntax
Die Syntax von setTimeout ist sehr einfach. Der erste Parameter ist die Rückruffunktion und der zweite Parameter ist die Verzögerungszeit. Die Funktion gibt eine eindeutige ID vom Typ numerischer Typ zurück. Diese ID kann als Parameter von clearTimeout verwendet werden, um den Timer abzubrechen:
var timeoutID = window.setTimeout(code, delay);
IE0+ unterstützt auch die Übergabe von Rückrufparametern:
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
setInterval()
MDN definiert setInterval als:
Rufen Sie regelmäßig eine Funktion auf oder führen Sie einen Code aus.
Da die Verwendung von setInterval und setTimeout gleich ist, werden sie hier nicht mehr aufgeführt.
Erklärung des zweiten Parameters (Verzögerung)
Aufgrund des Ereignisschleifenmechanismus von JavaScript bedeutet der zweite Parameter nicht, dass der Rückruf unmittelbar nach dem ausgeführt wird Versuchen Sie stattdessen, die Rückruffunktion zur Ereigniswarteschlange hinzuzufügen. Tatsächlich gibt es an dieser Stelle einen Unterschied in der Verarbeitung zwischen setTimeout und setInterval:
setTimeout: Nach den Millisekunden der Verzögerung wird die Rückruffunktion unabhängig davon direkt zum Ereignis hinzugefügt Warteschlange.
setInterval: Überprüfen Sie nach den Millisekunden der Verzögerung zunächst, ob sich in der Ereigniswarteschlange eine Rückruffunktion befindet, die noch nicht ausgeführt wurde (die Rückruffunktion von setInterval, falls vorhanden). nicht wieder in die Ereigniswarteschlange gehen. Eine Rückruffunktion wurde hinzugefügt.
Wenn es also zeitaufwändige Aufgaben in unserem Code gibt, verhält sich der Timer nicht so, wie wir denken.
Anhand eines Beispiels zum Verständnis des folgenden Codes
hatte ich ursprünglich gehofft, die Rückruffunktion bei 100 ms und 200 ms aufrufen zu können (d. h. einfach 100 ms warten). ):
var timerStart1 = now(); setTimeout(function () { console.log('第一个setTimeout回调执行等待时间:', now() - timerStart1); var timerStart2 = now(); setTimeout(function () { console.log('第二个setTimeout回调执行等待时间:', now() - timerStart2); }, 100); }, 100); // 输出: // 第一个setTimeout回调执行等待时间: 106 // 第二个setTimeout回调执行等待时间: 107
Das Ergebnis sieht so aus, wie wir es erwartet haben, aber sobald wir dem Code zeitaufwändige Aufgaben hinzufügen, ist das Ergebnis nicht das, was wir erwartet haben:
var timerStart1 = now(); setTimeout(function () { console.log('第一个setTimeout回调执行等待时间:', now() - timerStart1); var timerStart2 = now(); setTimeout(function () { console.log('第二个setTimeout回调执行等待时间:', now() - timerStart2); }, 100); heavyTask(); // 耗时任务 }, 100); var loopStart = now(); heavyTask(); // 耗时任务 console.log('heavyTask耗费时间:', now() - loopStart); function heavyTask() { var s = now(); while(now() - s < 1000) { } } function now () { return new Date(); } // 输出: // heavyTask耗费时间: 1015 // 第一个setTimeout回调执行等待时间: 1018 // 第二个setTimeout回调执行等待时间: 1000
Das Warten Die Ereignisse der beiden setTimeouts betragen aufgrund zeitaufwändiger Aufgaben nicht mehr 100 ms! Beschreiben wir, was passiert ist:
Zuerst beginnt die Ausführung der ersten zeitaufwändigen Aufgabe (heavyTask()), deren Abschluss etwa 1000 ms dauert.
Starten Sie die Ausführung der zeitaufwändigen Aufgabe. Nach 100 ms wird erwartet, dass die erste setTimeout-Rückruffunktion ausgeführt wird, daher wird sie zur Ereigniswarteschlange hinzugefügt, zu diesem Zeitpunkt jedoch die vorherige Die zeitaufwändige Aufgabe ist noch nicht abgeschlossen. Nach der Ausführung kann sie nur in der Warteschlange warten, bis die zeitaufwändige Aufgabe abgeschlossen ist. Das Ergebnis sehen wir also: Die erste Ausführungswartezeit des setTimeout-Rückrufs: 1018.
Sobald der erste setTimeout-Callback ausgeführt wird, wird der zweite setTimeout gestartet. Es wird auch erwartet, dass dieser Timer seine Callback-Funktion nach einer Verzögerung von 100 ms ausführt. Allerdings gibt es im ersten setTimeout eine weitere zeitaufwändige Aufgabe. Ihr Diagramm ist das gleiche wie beim ersten Timer, und es wird ebenfalls 1000 ms gewartet, bevor mit der Ausführung begonnen wird.
kann durch das folgende Bild zusammengefasst werden:
Sehen wir uns ein Beispiel für setInterval an:
var intervalStart = now(); setInterval(function () { console.log('interval距定义定时器的时间:', now() - loopStart); }, 100); var loopStart = now(); heavyTask(); console.log('heavyTask耗费时间:', now() - loopStart); function heavyTask() { var s = now(); while(now() - s < 1000) { } } function now () { return new Date(); } // 输出: // heavyTask耗费时间: 1013 // interval距定义定时器的时间: 1016 // interval距定义定时器的时间: 1123 // interval距定义定时器的时间: 1224
Im obigen Code gehen wir davon aus, dass alle 100 ms ein Protokoll gedruckt wird. Im Vergleich zu setTimeout ermittelt setInterval, ob sich nicht ausgeführte Rückrufe in der Warteschlange befinden, wenn die Rückruffunktion zur Ereigniswarteschlange hinzugefügt wird. Wenn dies der Fall ist, wird die Rückruffunktion nicht zur Warteschlange hinzugefügt. Andernfalls werden mehrere Rückrufe gleichzeitig ausgeführt.
kann durch das folgende Bild zusammengefasst werden:
Zusammenfassung:
Teil 1 Nach einer kurzen Analyse des Ausführungsprinzips des JavaScript-Timers glaube ich, dass meine Freunde ein gewisses Verständnis für das Funktionsprinzip des JavaScript-Timers haben.
Verwandte Empfehlungen:
Eingehende Untersuchung von Javascript-Timern
Vollständiges Beispiel eines Javascript-Timers
JavaScript-Timer und optimierte Abbruch-Timer-Methode
Das obige ist der detaillierte Inhalt vonAnalyse der Prinzipien von Timern in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!