SetTimeOut und SetInterval, welche sind in JavaScript besser zu verwenden? Informationen zur Funktionsweise von JavaScript-Timern: JQuery-Intervall für die Ausführung einer Funktion

💖 Gefällt es dir? Teilen Sie den Link mit Ihren Freunden

JavaScript-Timeout ist eine native Javascript-Funktion, die einen Codeabschnitt nach einer bestimmten Zeitverzögerung (in Millisekunden) ausführt. Dies kann nützlich sein, wenn Sie ein Popup anzeigen müssen, nachdem der Benutzer einige Zeit auf Ihrer Seite verbracht hat. Oder möchten Sie, dass der Effekt, wenn Sie mit der Maus über ein Element fahren, erst nach einiger Zeit einsetzt? Auf diese Weise können Sie verhindern, dass ein Effekt unbeabsichtigt ausgelöst wird, wenn der Benutzer versehentlich mit der Maus darüber fährt.

Einfaches setTimeout-Beispiel

Um zu demonstrieren, wie diese Funktion funktioniert, empfehle ich einen Blick auf die folgende Demo, in der zwei Sekunden nach dem Klicken auf die Schaltfläche ein Popup-Fenster erscheint.

Demo ansehen

Syntax

Die MDN-Dokumentation stellt die folgende Syntax für setTimeout bereit:

var timeoutID = window.setTimeout(func, ); var timeoutID = window.setTimeout(code, );

  • timeoutID – eine numerische ID, die in Kombination mit clearTimeout() verwendet werden kann, um den Timer zu deaktivieren;
  • func – auszuführende Funktion;
  • Code ( in alternativer Syntax) – auszuführende Codezeile;
  • Verzögerung – die Dauer der Verzögerung in Millisekunden, nach der die Funktion gestartet wird. Der Standardwert ist 0.

setTimeout vs. window.setTimeout

Die obige Syntax verwendet window.setTimeout . Warum?

Tatsächlich sind setTimeout und window.setTimeout praktisch dieselbe Funktion. Der einzige Unterschied besteht darin, dass wir im zweiten Ausdruck die Methode setTimeout als Eigenschaft des globalen Fensterobjekts verwenden.

Persönlich denke ich, dass dies den Code nur viel komplizierter macht. Wenn wir eine Alternative definieren würden JavaScript-Methode timeout , das vorrangig gefunden und zurückgegeben werden könnte, würden wir auf noch mehr Probleme stoßen.

IN dieses Handbuch Ich möchte mich nicht mit dem Fensterobjekt herumschlagen, aber im Allgemeinen liegt es an Ihnen, welche Syntax Sie verwenden.

Anwendungsbeispiele

Dies könnte der Name der Funktion sein:

function explosion())( alarm("Boom!"); ) setTimeout(explode, 2000);

Variable, die sich auf die Funktion bezieht:

var explosion = function())( alarm("Boom!"); ); setTimeout(explode, 2000);

Oder eine anonyme Funktion:

setTimeout(function())( alarm("Boom!"); , 2000);

  • Dieser Code ist nur unzureichend verstanden und daher schwer zu modernisieren oder zu debuggen.
  • Dabei kommt die Methode eval() zum Einsatz, die eine potenzielle Sicherheitslücke darstellen könnte;
  • Diese Methode ist langsamer als andere, da sie ausgeführt werden muss JavaScript-Interpreter.

Beachten Sie außerdem, dass wir zum Testen des Codes die JavaScript-Timeout-Warnmethode verwenden.

Übergabe von Parametern an setTimout

In der ersten ( außerdem browserübergreifend)-Option übergeben wir Parameter an die Callback-Funktion, die mit setTimeout ausgeführt wird.

Im folgenden Beispiel extrahieren wir eine zufällige Begrüßung aus dem Greetings-Array und übergeben sie als Parameter an die Funktion „greet()“, die von setTimeout mit einer Verzögerung von 1 Sekunde ausgeführt wird:

function meet(greeting)( console.log(greeting); ) function getRandom(arr)( return arr; ) var Greetings = ["Hello", "Bonjour", "Guten Tag"], randomGreeting = getRandom(greetings); setTimeout(function())(greet(randomGreeting); ), 1000);

Demo ansehen

Alternative Methode

In der am Anfang des Artikels angegebenen Syntax gibt es eine weitere Methode, mit der Sie Parameter an die durch JavaScript-Timeout ausgeführte Rückruffunktion übergeben können. Diese Methode impliziert die Ausgabe aller Parameter nach der Verzögerung.

Basierend auf dem vorherigen Beispiel erhalten wir:

setTimeout(greet, 1000, randomGreeting);

Diese Methode funktioniert nicht in IE 9 und niedriger, wo die übergebenen Parameter als undefiniert behandelt werden. Aber um dieses Problem zu lösen MDN verfügt über eine spezielle Polyfüllung.

Verwandte Probleme und „dieses“

Der von setTimeout ausgeführte Code wird getrennt von der Funktion ausgeführt, die ihn aufgerufen hat. Aus diesem Grund stehen wir vor bestimmten Problemen, deren Lösung genutzt werden kann Stichwort Das.

var person = ( Vorname: „Jim“, vorstellen: function())( console.log(„Hi, ich“m „ + this.firstName); ) ); person.introduce(); // Ausgaben: Hallo, ich " m Jim setTimeout(person.introduce, 50); // Ausgaben: Hallo, ich bin undefiniert

Der Grund für diese Ausgabe ist, dass sie im ersten Beispiel auf das Personenobjekt zeigt und im zweiten Beispiel auf das globale Fensterobjekt, das keine firstName-Eigenschaft hat.

Um diese Inkonsistenz zu beseitigen, können Sie verschiedene Methoden anwenden:

Erzwingen Sie die Einstellung

Dies kann mit bind() erfolgen, einer Methode, die erstellt neue Funktion, der beim Aufruf einen bestimmten Wert als Wert dieses Schlüssels verwendet. In unserem Fall das angegebene Personenobjekt. Das ergibt letztlich:

setTimeout(person.introduce.bind(person), 50);

Hinweis: Die Bind-Methode wurde in ECMAScript 5 eingeführt, was bedeutet, dass sie nur in modernen Browsern funktioniert. In anderen Fällen erhalten Sie bei der Verwendung einen Laufzeitfehler JavaScript „Funktions-Timeout-Fehler“.

Bibliothek nutzen

Viele Bibliotheken enthalten integrierte Funktionen, die zur Lösung dieses Problems erforderlich sind. Zum Beispiel die Methode jQuery.proxy(). Es übernimmt eine Funktion und gibt eine neue zurück, die immer einen bestimmten Kontext verwendet. In unserem Fall wäre der Kontext:

setTimeout($.proxy(person.introduce, person), 50);

Demo ansehen

Deaktivieren des Timers

Der Rückgabewert von setTimeout ist eine numerische ID, die zum Deaktivieren des Timers mithilfe der Funktion „clearTimeout()“ verwendet werden kann:

var timer = setTimeout(myFunction, 3000); clearTimeout(timer);

Sehen wir es uns in Aktion an. Klicken Sie im folgenden Beispiel auf die Schaltfläche „ Countdown starten", der Countdown beginnt. Sobald es fertig ist, bekommen die Kätzchen ihr eigenes. Aber wenn Sie den Knopf drücken Stoppen Sie den Countdown", wird der JavaScript-Timeout gestoppt und zurückgesetzt.

Beispiel ansehen

Fassen wir es zusammen

setTimeout ist eine asynchrone Funktion, was bedeutet, dass der resultierende Aufruf dieser Funktion in eine Warteschlange gestellt wird und erst ausgeführt wird, nachdem alle anderen Aktionen auf dem Stapel abgeschlossen sind. Es kann nicht gleichzeitig mit anderen Funktionen oder einem separaten Thread ausgeführt werden.

Es ist äußerst wichtig zu verstehen, wie JavaScript-Timer funktionieren. Ihr Verhalten entspricht oft nicht unserem intuitiven Verständnis von Multithreading, und das liegt daran, dass sie in Wirklichkeit in einem einzigen Thread ausgeführt werden. Schauen wir uns vier Funktionen an, mit denen wir Timer verwalten können:

  • var id = setTimeout(fn, Verzögerung); – Erstellt einen einfachen Timer, der eine bestimmte Funktion nach einer bestimmten Verzögerung aufruft. Die Funktion gibt eine eindeutige ID zurück, mit der der Timer angehalten werden kann.
  • var id = setInterval(fn, Verzögerung); – Ähnlich wie setTimeout, ruft die Funktion jedoch kontinuierlich in einem angegebenen Intervall auf (bis sie gestoppt wird).
  • clearInterval(id);, clearTimeout(id); – Akzeptiert eine Timer-ID (zurückgegeben von einer der oben beschriebenen Funktionen) und stoppt die Ausführung des Rückrufs „a“.
Der wichtigste zu berücksichtigende Gedanke besteht darin, dass die Genauigkeit der Timer-Verzögerungsperiode nicht garantiert werden kann. Zunächst führt der Browser alle asynchronen JavaScript-Ereignisse in einem Thread aus (z. B. Mausklicks oder Timer) und nur zu dem Zeitpunkt, zu dem dieses Ereignis an der Reihe ist. Dies lässt sich am besten anhand des folgenden Diagramms veranschaulichen:

Diese Abbildung enthält eine Menge Informationen, aber wenn Sie sie verstehen, erhalten Sie ein tieferes Verständnis dafür, wie JavaScript-Asynchronität funktioniert. Dieses Diagramm stellt die Zeit vertikal in Millisekunden dar, die blauen Blöcke zeigen Blöcke von JavaScript-Code, die ausgeführt wurden. Beispielsweise wird der erste Block im Durchschnitt in 18 ms ausgeführt, ein Mausklick blockiert die Ausführung für etwa 11 ms usw.

JavaScript kann nur einen Codeblock ausführen (aufgrund der Single-Threaded-Ausführung), der jeweils die Ausführung anderer asynchroner Ereignisse blockiert. Das heißt, wenn ein asynchrones Ereignis auftritt (z. B. ein Mausklick, ein Timer-Aufruf oder der Abschluss einer XMLHttp-Anfrage), wird es einer Warteschlange hinzugefügt und später ausgeführt (die Implementierung variiert natürlich je nach Browser, aber wir stimmen dem zu). nennen Sie es eine „Warteschlange“).

Stellen wir uns zunächst vor, dass zwei Timer innerhalb eines JavaScript-Blocks starten: setTimeout mit einer Verzögerung von 10 ms und setInterval mit derselben Verzögerung. Abhängig davon, wann der Timer startet, wird er in dem Moment ausgelöst, in dem wir den ersten Codeblock noch nicht abgeschlossen haben. Beachten Sie jedoch, dass es nicht sofort ausgelöst wird (dies ist aufgrund des Single-Threadings nicht möglich). Stattdessen wird die verzögerte Funktion in die Warteschlange gestellt und zum nächsten verfügbaren Zeitpunkt ausgeführt.

Außerdem erfolgt während der Ausführung des ersten JavaScript-Blocks ein Mausklick. Der Handler für dieses asynchrone Ereignis (und es ist asynchron, weil wir es nicht vorhersagen können) kann zu diesem Zeitpunkt nicht direkt ausgeführt werden, sodass es wie der Timer ebenfalls in einer Warteschlange landet.

Nachdem der erste Block JavaScript-Code ausgeführt wurde, stellt der Browser die Frage: „Was wartet darauf, ausgeführt zu werden?“ In diesem Fall befinden sich der Mausklick-Handler und der Timer im Wartezustand. Der Browser wählt einen davon aus (den Click-Handler) und führt ihn aus. Der Timer wartet auf den nächsten verfügbaren Zeitblock in der Ausführungswarteschlange.

Beachten Sie, dass während der Ausführung des Mausklick-Handlers der erste Intervall-Callback ausgelöst wird. Genau wie der Timer-Rückruf wird er in die Warteschlange gestellt. Beachten Sie jedoch, dass das Intervall aus der Warteschlange entfernt wird, wenn es erneut ausgelöst wird (während der Timer-Rückruf ausgeführt wird). Wenn „jeder „Intervall-Callback““ in die Warteschlange gestellt würde, während ein großer Teil des Codes ausgeführt wird, würde dies dazu führen, dass eine Reihe von Funktionen darauf warten, aufgerufen zu werden, und dass zwischen ihnen keine Verzögerungszeiten liegen, bis ihre Ausführung abgeschlossen ist. Stattdessen neigen Browser dazu, zu warten, bis keine vorhanden sind Weitere Funktionen verbleiben in der Warteschlange, bevor eine weitere zur Warteschlange hinzugefügt wird.

Somit können wir den Fall beobachten, dass die dritte Auslösung des Intervall-Callbacks mit dem Moment zusammenfällt, in dem er bereits ausgeführt wird. Dies verdeutlicht einen wichtigen Punkt: Intervallen ist es egal, was gerade läuft, sie werden der Warteschlange hinzugefügt, ohne Rücksicht auf die Verzögerungszeit zwischen den Ausführungen.

Nachdem der zweite Intervall-Callback abgeschlossen ist, werden wir schließlich feststellen, dass nichts mehr für die Ausführung durch die JavaScript-Engine übrig ist. Dies bedeutet, dass der Browser erneut auf das Auftreten neuer asynchroner Ereignisse wartet. Dies geschieht bei der 50-ms-Marke, wo der Intervall-Callback wieder funktioniert. Zu diesem Zeitpunkt gibt es nichts, was es blockieren könnte, sodass es sofort funktioniert.

Schauen wir uns ein Beispiel an, das den Unterschied zwischen setTimeout und setInterval gut veranschaulicht.
setTimeout(function())( /* Ein langer Codeblock... */ setTimeout(arguments.callee, 10); ), 10); setInterval(function())( /* Ein langer Codeblock... */ ), 10);
Diese beiden Optionen sind auf den ersten Blick gleichwertig, in Wirklichkeit jedoch nicht. Code, der setTimeout verwendet, hat immer eine Verzögerung von mindestens 10 ms nach dem vorherigen Aufruf (es kann mehr, aber niemals weniger sein), während Code, der setInterval verwendet, dazu tendiert, alle 10 ms aufgerufen zu werden, unabhängig davon, wann der vorherige Aufruf erfolgte.

Fassen wir alles zusammen, was oben gesagt wurde:
- JavaScript-Engines verwenden eine Single-Threaded-Umgebung und wandeln asynchrone Ereignisse in eine Warteschlange um, die auf ihre Ausführung wartet.
- Die Funktionen setTimeout und setInterval werden in asynchronem Code grundsätzlich unterschiedlich ausgeführt.
- Wenn der Timer nicht ausgeführt werden kann dieser Moment, es wird bis zum nächsten Ausführungspunkt verzögert (der länger als die gewünschte Verzögerung sein wird),
- Intervalle (setInterval) können ohne Verzögerung nacheinander ausgeführt werden, wenn ihre Ausführung länger als die angegebene Verzögerung dauert.

Das alles ist extrem wichtige Informationen zur Entwicklung. Wenn Sie wissen, wie die JavaScript-Engine funktioniert, insbesondere bei vielen asynchronen Ereignissen (was häufig vorkommt), ist dies eine gute Grundlage für die Erstellung komplexer Anwendungen.

Quelle: http://learn.javascript.ru/settimeout-setinterval

Fast alle JavaScript-Implementierungen verfügen über einen internen Timer-Scheduler, mit dem Sie den Aufruf einer Funktion nach einem bestimmten Zeitraum planen können.

Diese Funktion wird insbesondere in Browsern und im Node.JS-Server unterstützt.

setTimeout

Syntax:

var timerId = setTimeout(func/code, delay[, arg1, arg2...])

Optionen:

  • Funktion/Code
    • Eine Funktion oder Codezeile, die ausgeführt werden soll.
    • Die Zeichenfolge wird aus Kompatibilitätsgründen beibehalten und wird nicht empfohlen.
  • Verzögerung
    • Latenz in Millisekunden, 1000 Millisekunden entsprechen 1 Sekunde.
  • arg1, arg2…
    • Argumente, die an die Funktion übergeben werden sollen. Wird in IE9- nicht unterstützt.
    • Die Funktion wird nach der im Verzögerungsparameter angegebenen Zeit ausgeführt.

Der folgende Code löst beispielsweise nach einer Sekunde eine Warnung („Hallo“) aus:

Funktion func()( alarm("Hallo" ); ) setTimeout(func, 1000 );

Wenn das erste Argument eine Zeichenfolge ist, erstellt der Interpreter aus dieser Zeichenfolge eine anonyme Funktion.

Das heißt, dieser Eintrag funktioniert genauso:

SetTimeout("alert("Hello")" , 1000 );

Verwenden Sie stattdessen anonyme Funktionen:

SetTimeout( Funktion()( Alert("Hallo" ) ), 1000 );

Parameter für Funktion und Kontext

In allen modernen Browsern, einschließlich IE10, können Sie mit setTimeout Funktionsparameter angeben.

Im folgenden Beispiel wird überall außer IE9 „Hallo, ich bin Vasya“ angezeigt:

Funktion sayHi (wer)( alarm("Hi, ich bin " + who); ) setTimeout(sayHi, 1000, "Vasya" );

...Allerdings benötigen wir in den meisten Fällen Unterstützung vom alten IE, der die Angabe von Argumenten nicht zulässt. Um sie weiterzuleiten, packen sie den Anruf daher in eine anonyme Funktion:

Funktion sayHi (wer)( Alert("Hallo, ich bin " + wer); ) setTimeout( Funktion()( sayHi("Vasya")), 1000);

Beim Aufruf von setTimeout wird dieser Kontext nicht übergeben.

Insbesondere der Aufruf einer Objektmethode über setTimeout funktioniert im globalen Kontext. Dies kann zu falschen Ergebnissen führen.

Rufen wir zum Beispiel user.sayHi() nach einer Sekunde auf:

Funktion Benutzer (ID) Funktion()( Alert(diese .id); ); ) var user = neuer Benutzer(12345); setTimeout(user.sayHi, 1000 ); // erwartet 12345, gibt aber „undefiniert“ aus

Da setTimeout die Funktion user.sayHi im globalen Kontext ausführt, hat es über this keinen Zugriff auf das Objekt.

Mit anderen Worten, diese beiden Aufrufe von setTimeout bewirken dasselbe:

// (1) eine Zeile setTimeout(user.sayHi, 1000 ); // (2) das Gleiche in zwei Zeilen var func = user.sayHi; setTimeout(func, 1000 );

Glücklicherweise lässt sich dieses Problem auch leicht lösen, indem man eine Zwischenfunktion erstellt:

Funktion Benutzer (ID)( this .id = id; this .sayHi = Funktion()( Alert(diese .id); ); ) var user = neuer Benutzer(12345); setTimeout( Funktion()( user.sayHi(); , 1000 );

Eine Wrapper-Funktion wird verwendet, um Argumente browserübergreifend zu übergeben und den Ausführungskontext beizubehalten.

Abbruch der Ausführung

Die Funktion setTimeout gibt eine Timer-ID zurück, mit der die Aktion abgebrochen werden kann.

Syntax:

ClearTimeout(timerId)

Im folgenden Beispiel legen wir ein Timeout fest und löschen dann (wir haben es uns anders überlegt). Infolgedessen passiert nichts.

var timerId = setTimeout( Funktion()( Alert(1) ), 1000 ); clearTimeout(timerId);

setInterval

Die setInterval-Methode hat eine ähnliche Syntax wie setTimeout.

var timerId = setInterval(func/code, delay[, arg1, arg2...])

Die Bedeutung der Argumente ist dieselbe. Im Gegensatz zu setTimeout wird die Funktion jedoch nicht einmal ausgeführt, sondern regelmäßig in einem bestimmten Zeitintervall wiederholt. Sie können die Ausführung stoppen, indem Sie Folgendes aufrufen:

ClearInterval(timerId)

Das folgende Beispiel zeigt bei der Ausführung alle zwei Sekunden eine Meldung an, bis Sie auf die Schaltfläche „Stopp“ klicken:

<Eingabetyp ="Schaltfläche" onclick ="clearInterval(timer)" value ="Stop" > !} <Skript > var i = 1 ; var timer = setInterval( Funktion()( alarm(i++) ), 2000 );Skript >

Einreihen und Überlagern von Anrufen in setInterval

Der Aufruf setInterval(function, delay) bewirkt, dass die Funktion im angegebenen Zeitintervall ausgeführt wird. Aber hier gibt es eine Feinheit.

Tatsächlich ist die Pause zwischen den Anrufen kürzer als das angegebene Intervall.

Nehmen wir zum Beispiel setInterval(function() ( func(i++) ), 100) . Es führt func alle 100 ms aus und erhöht den Zähler jedes Mal.

Im Bild unten ist der rote Block die Ausführungszeit von func. Die Interblockzeit ist die Zeit zwischen Funktionsläufen und ist kleiner als die eingestellte Verzögerung!

Das heißt, der Browser initiiert den Start der Funktion alle 100 ms, ohne die Ausführungszeit der Funktion selbst zu berücksichtigen.

Es kommt vor, dass die Ausführung einer Funktion länger dauert als die Verzögerung. Beispielsweise ist die Funktion komplex, die Verzögerung jedoch gering. Oder die Funktion enthält Warnungs-/Bestätigungs-/Eingabeaufforderungsanweisungen, die den Ausführungsthread blockieren. Hier beginnt es interessant zu werden.

Wenn eine Funktion nicht gestartet werden kann, weil der Browser ausgelastet ist, wird sie in die Warteschlange gestellt und ausgeführt, sobald der Browser frei ist.

Das Bild unten zeigt, was bei einer Funktion passiert, deren Ausführung lange dauert.

Der von setInterval initiierte Funktionsaufruf wird zur Warteschlange hinzugefügt und erfolgt nach Möglichkeit sofort:

Der zweite Start der Funktion erfolgt unmittelbar nach dem Ende des ersten:

Die Ausführung wird nicht mehr als einmal in die Warteschlange gestellt.

Wenn die Ausführung einer Funktion länger dauert als mehrere geplante Ausführungen, wird sie dennoch einmal in die Warteschlange gestellt. Es gibt also keine „Anhäufung“ von Starts.

Im Bild unten versucht setInterval, die Funktion innerhalb von 200 ms auszuführen und stellt den Aufruf in die Warteschlange. Bei 300ms und 400ms wacht der Timer wieder auf, aber es passiert nichts.

Der Aufruf von setInterval(function, delay) garantiert keine tatsächliche Verzögerung zwischen den Ausführungen.

Es gibt Fälle, in denen die tatsächliche Verzögerung größer oder kleiner als die angegebene ist. Im Allgemeinen ist es keine Tatsache, dass es zumindest zu einer gewissen Verzögerung kommen wird.

Wiederholtes verschachteltes setTimeout

In Fällen, in denen Sie nicht nur eine regelmäßige Wiederholung, sondern eine obligatorische Verzögerung zwischen den Starts benötigen, verwenden Sie Neuinstallation setTimeout jedes Mal, wenn die Funktion ausgeführt wird.

Unten sehen Sie ein Beispiel, das eine Warnung mit Abständen von 2 Sekunden ausgibt.

<Eingabetyp ="button" onclick ="clearTimeout(timer)" value ="Stop" > !} <Skript > var i = 1 ; var timer = setTimeout( Funktion run()( alarm(i++); timer = setTimeout(run, 2000); ), 2000);Skript >

Die Ausführungszeitleiste weist feste Verzögerungen zwischen den Ausführungen auf. Abbildung für 100 ms Verzögerung:

Minimale Timerverzögerung

Der Browser-Timer hat die geringstmögliche Latenz. Sie variiert in modernen Browsern zwischen etwa null und 4 ms. Bei älteren Geräten kann es länger sein und 15 ms erreichen.

Laut Norm beträgt die Mindestverzögerung 4 ms. Es gibt also keinen Unterschied zwischen setTimeout(..,1) und setTimeout(..,4) .

Das latenzfreie Verhalten von setTimeout und setInterval ist browserspezifisch.

  1. In Opera ist setTimeout(.., 0) dasselbe wie setTimeout(.., 4) . Es wird seltener ausgeführt als setTimeout(.. ,2). Dies ist eine Funktion dieses Browsers.
  2. IN Internet Explorer, Nullverzögerung setInterval(.., 0) wird nicht funktionieren. Dies gilt insbesondere für setInterval , d. h. setTimeout(.., 0) funktioniert gut.

Tatsächliche Triggerfrequenz

Die Auslösung kann viel seltener erfolgen. In einigen Fällen beträgt die Verzögerung möglicherweise nicht 4 ms, sondern 30 ms oder sogar 1000 ms.

Die meisten Browser (hauptsächlich Desktop-Browser) führen weiterhin setTimeout / setInterval aus, auch wenn die Registerkarte inaktiv ist. Gleichzeitig reduzieren einige von ihnen (Chrome, FF, IE10) die minimale Timerfrequenz auf 1 Mal pro Sekunde. Es stellt sich heraus, dass der Timer auf der Registerkarte „Hintergrund“ funktioniert, jedoch selten.

Wenn Browser auf einem Laptop mit Batteriestrom betrieben werden, können sie außerdem die Häufigkeit reduzieren, mit der Code seltener ausgeführt wird, und Batteriestrom sparen. IE ist dafür besonders bekannt. Die Reduzierung kann je nach Einstellung ein Mehrfaches erreichen. Wenn die CPU-Last zu hoch ist, ist JavaScript möglicherweise nicht in der Lage, Timer rechtzeitig zu verarbeiten. Dadurch werden einige setInterval-Läufe übersprungen.

Fazit: Es lohnt sich, auf eine Frequenz von 4 ms zu achten, aber man sollte sich nicht darauf verlassen.

Intervalle an die Konsole ausgeben Der Code, der die Zeitintervalle zwischen Aufrufen zählt, sieht etwa so aus:

var timeMark = neues Datum; setTimeout( Funktion go()( var diff = neues Datum - timeMark; // die nächste Verzögerung an die Konsole statt an die Seite ausgeben Konsole .log(diff); // Erinnere dich an die Zeit ganz am Ende, // um die Verzögerung zwischen Aufrufen zu messen timeMark = neues Datum ; setTimeout(go, 100); ), 100 );

Der Trick ist setTimeout(func, 0)

Dieser Trick ist es wert, in die Annalen der JavaScript-Hacks aufgenommen zu werden.

Die Funktion wird in setTimeout(func, 0) eingeschlossen, wenn Sie sie nach dem Ende des aktuellen Skripts ausführen möchten.

Die Sache ist, dass setTimeout die Funktion nie sofort ausführt. Er plant nur die Umsetzung. Der JavaScript-Interpreter beginnt jedoch erst mit der Ausführung der geplanten Funktionen, nachdem das aktuelle Skript ausgeführt wurde.

Laut Standard kann setTimeout ohnehin keine Funktion mit einer Verzögerung von 0 ausführen. Wie bereits erwähnt, beträgt die Verzögerung normalerweise 4 ms. Aber die Hauptsache hier ist, dass die Ausführung in jedem Fall nach der Ausführung des aktuellen Codes erfolgt.

Zum Beispiel:

var-Ergebnis; Funktion showResult()( alarm(result); ) setTimeout(showResult, 0 ); Ergebnis = 2 *2 ; // gibt 4 aus

Gesamt

Mit den Methoden setInterval(func, Delay) und setTimeout(func, Delay) können Sie func regelmäßig/einmal alle Millisekunden der Verzögerung ausführen.

Beide Methoden geben die Timer-ID zurück. Es wird verwendet, um die Ausführung durch den Aufruf von clearInterval / clearTimeout zu stoppen.

| | setInterval | setTimeout | || ----------- | ---------- | | Zeiteinteilung | Der Anruf erfolgt ausschließlich nach einem Timer. Wenn der Dolmetscher besetzt ist, wird ein Anruf in die Warteschlange gestellt. Die Ausführungszeit der Funktion wird nicht berücksichtigt, daher kann das Zeitintervall vom Ende eines Laufs bis zum Beginn eines anderen variieren. | Anstelle von setInterval wird ein rekursiver Aufruf von setTimeout verwendet, wenn eine feste Pause zwischen den Ausführungen erforderlich ist. | | Verzögerung | Mindestverzögerung: 4 ms. | Mindestverzögerung: 4 ms. | | Browserfunktionen | Latenz 0 funktioniert im IE nicht. | In Opera entspricht eine Latenz von Null 4 ms, und andere Verzögerungen werden genau behandelt, einschließlich nicht standardmäßiger 1 ms, 2 ms und 3 ms. |

Beim Programmieren in Skriptsprachen besteht regelmäßig die Notwendigkeit, eine Pause zu erstellen – um die Ausführung des Programms für eine Weile anzuhalten und dann mit der Arbeit fortzufahren. In VBS- und PHP-Skripten sind beispielsweise folgende Methoden möglich:

VBS: wscript.sleep 1500 (1,5 Sekunden lang anhalten)

PHP: Sleep(10); (10 Sekunden lang anhalten)

Während solcher Pausen wird das Laufzeitsystem (PHP oder VBS) nichts tun. Ein Entwickler, der versucht, etwas Ähnliches in Javascript intuitiv zu verwenden, wird unangenehm überrascht sein. Häufiger Fehler Beim Versuch, eine Pause in Javascript zu erstellen, sieht es so aus:

Funktion badtest() ( für (var i=1; i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

Denken Sie, dass, wenn während des Zyklus die nächste Zahl gezogen wird, Ihre … setTimeout werde ehrlich gesagt aufhören Javascript-Arbeit, wartet 0,9 Sekunden, fügt die erforderliche Zahl am Ende des Eingabefelds hinzu und arbeitet dann weiter. Aber eigentlich ist es nicht: setInterval Und setTimeout In Javascript wird nur die in Klammern angegebene Aktion (oder Funktion) zurückgestellt. In unserem Beispiel wird Folgendes passieren:

  1. ich = 1;
  2. das Hinzufügen der Zahl „1“ zum Eingabefeld um 0,9 Sekunden verzögern;
  3. sofort Nachdem dieses Problem gelöst wurde, geht der Zyklus weiter: i=2;
  4. das Hinzufügen der Zahl „2“ zum Eingabefeld um 0,9 Sekunden verzögern;

Sofort bedeutet beispielsweise 1 ms (also unverhältnismäßig klein im Vergleich zu 900 ms): Die Schleife erledigt ihre Arbeit fast augenblicklich und erstellt mehrere verzögerte Aufgaben zum gleichen Zeitpunkt. Das bedeutet, dass alle anstehenden „Zeichnungs“-Aufgaben nahezu gleichzeitig erledigt werden, ohne Pausen zwischen dem Hinzufügen neuer Zahlen. Der Zyklus beginnt; alles friert für 0,9 s ein; und schirren – alle Zahlen werden nacheinander hintereinander geschossen.

Wie wendet man es in einem solchen Fall richtig an? setTimeout? Das ist schwer. Sie müssen die Funktion aufrufen rekursiv(innerhalb der Funktion die gleiche Funktion), und damit dieser Prozess nicht endlos ist, legen Sie eine Stoppbedingung fest (z. B. die Größe der zu druckenden Zahl):

Funktion welltest() ( if (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

Und noch eine Variable ich Sie müssen außerhalb der Funktion initialisieren – zum Beispiel so:

Jetzt funktioniert alles wie es soll (wir haben die Verzögerungszeit von 0,9 s auf 0,4 s reduziert). Für solche Aufgaben ist es jedoch logischer, sie nicht zu verwenden setTimeout A setInterval(obwohl dies zwei Funktionen erfordert):

Funktion besttest() ( window.i = 0 window.timer1 = window.setInterval("draw()", 400) ) function draw() ( document.getElementById("test3").value += ++i if (i >= 9) clearInterval(window.timer1) )

Merkmal der Javascript-Methode setInterval Da es nicht „von selbst“ verschwindet, muss es mit einer speziellen Methode gestoppt werden klaresIntervall. Und um zu verdeutlichen, was genau gestoppt werden soll, wird der Aufgabe für die verzögerte Aktion eine spezielle Kennung zugewiesen – ein Timer: window.timer1 = window.setInterval(...) .

Den durch die Methode erstellten Aufgaben können auch Bezeichner zugewiesen werden setTimeout. Alle Timer-IDs müssen voneinander verschieden sein (eindeutig innerhalb des aktuellen Browserfensters). Dann können Sie im Fenster mehrere verschiedene Aufgaben erstellen, die verzögerte Aktionen verwenden, und diese Aufgaben werden parallel ausgeführt (sozusagen gleichzeitig, wenn der Computer über genügend Ressourcen verfügt), was in PHP oder VBS grundsätzlich unmöglich ist.

Hier ist ein Beispiel für eine Seite mit mehreren gleichzeitig laufenden Javascript-Timern: setinterval.htm (Javascript-Funktionen in der Datei setinterval.js). Alle Seiten-Timer (außer Menü) können mit der Esc-Taste gestoppt werden. Alle Beispiel-Timer basieren auf „natürlich“ (nicht abstrakt). i++) Countdown – Zeit oder Distanz. Alle „Uhren“ sind speziell desynchronisiert (aus Gründen der Übersichtlichkeit). Distanzabhängige Timer werden im „Indikator“ und im Dropdown-Menü („Pull-Out“) verwendet.

Dropdown-Menü

Unser Schiebemenü ist eigentlich ein Schiebemenü (unter der „Kopfzeile“): Zwischen den Elementen werden speziell Lücken gelassen, damit Sie sehen können, wie es herausgleitet. Unerwarteterweise stellte sich heraus, dass wir für Listen unterschiedlicher Länge keine gleichermaßen reibungslosen Exits durchführen konnten – wahrscheinlich aufgrund der geringen Computerleistung ( AMD Athlon 999 MHz).

Es liegt auf der Hand, dass es für Schönheit und Harmonie notwendig ist, dass die Listen verschiedener Menüpunkte gleichzeitig angezeigt werden. Das heißt, längere Listen sollten mit mehr herausfallen hohe Geschwindigkeit, kürzere - mit geringerer Geschwindigkeit. Es scheint, dass dies folgendermaßen umgesetzt werden könnte:

  1. Die gesamte „Abfahrtszeit“ stellen wir beispielsweise auf 200 ms ein.
  2. Wenn die Dropdown-Liste eine Höhe von 20 Pixel hat, ist es offensichtlich, dass wir sie alle 10 ms um ein Pixel nach unten verschieben können – und dann wird in 200 ms die gesamte Liste angezeigt.
  3. Wenn das Dropdown-Menü 40 Pixel hoch ist, müssen wir es alle 5 ms um ein Pixel nach unten verschieben, damit es in die gleiche Zeit passt.

Wenn die Dropdown-Liste 200 Pixel hoch ist, sollten wir sie nach dieser Logik alle 1 ms um ein Pixel nach unten verschieben. Eine solche Geschwindigkeit funktioniert auf unserem Computer jedoch nicht – der Browser hat einfach keine Zeit, die neue Position der Liste in einer Millisekunde zu zeichnen. Ja. Javascript schafft es zu zählen (was gibt es zu zählen?), aber der Browser (Firefox) hat keine Zeit zum Anzeigen. Typische Situation für das Web.

Daher ist es nur mit Hilfe von Krücken möglich, die Essensausgabezeit mehr oder weniger anzugleichen, und es ist noch unklar, wie dies für mehr funktionieren wird schneller Computer. Aber wir sollten uns auf den langsamsten verlassen, oder? Der Algorithmus (ohne Berücksichtigung der Geschwindigkeit des Computers) sieht in etwa so aus:

  1. Legen Sie die Gesamtzeit für das Auschecken der Liste fest: Zeit = 224 (ms).
  2. Wir legen die Mindestzeit für ein Intervall im Zyklus fest: Verzögerung = 3 (ms).
  3. Legen Sie den Mindestschritt zum Verschieben der Liste fest: Offset = 1 (px).
  4. Wir ändern dies alles abhängig von der Höhe der Liste: 1) Erhöhen Sie die Verzögerungszeit (Intervallzeit) umgekehrt proportional zur Höhe und direkt proportional zur Gesamtzeit (bei einer Höhe von 224 beträgt der Koeffizient 1); 2) Wenn die Höhe mehr als 40 Pixel beträgt, erhöhen Sie den Mindestschritt proportional zur Höhe. Die Konstante „40“ wurde experimentell für den langsamsten Computer ermittelt. Tests auf einem Computer mit Pentium 4-CPU und 2,53 GHz ergaben genau die gleiche Zahl – 40. Andernfalls geraten die Timer außer Betrieb, und die Listen geraten aus dem Takt.

Jetzt kommen die Listen mehr oder weniger heraus. Für mehr oder weniger ähnliche Zeit. Auf der Seite setinterval.htm.

Und hier kommt Bruce:

Funktion slide_do(obj, maxtop, offset) ( if (getTopLeft(obj).top< maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }

Die Funktion selbst, die verschachtelte Listen aus dem Menü schiebt, ist, wie wir sehen können, sehr einfach. Jetzt müssen Sie es nur noch mit etwa dieser Zeile ausführen:

Ts.timer1 = setInterval(function())(slide_do(ts, maxtop, offset)), Verzögerung)

Nun, bevor Sie beginnen, berechnen Sie einfach alle diese Maxtop- und Offset-Werte und platzieren Sie die Liste auch an der Mintop-Position. Was macht die Funktion „Vorläufig“? gleiten() 40 Zeilen groß. Und alles zusammen - in der Datei setinterval.js. Ja, und dieser Mist funktioniert ohne die mitgelieferte Styles-Datei überhaupt nicht

  • Aus:
  • Eingetragen: 2014.07.08
  • Beiträge: 3,896
  • Likes: 497

Thema: SetTimeOut und SetInterval, was ist besser in JavaScript zu verwenden?

Um Code mehrmals in regelmäßigen Abständen auszuführen, verwenden Sie die Funktion setInterval. Es hat jedoch eine Reihe von Nachteilen, vor allem ein unterschiedliches Verhalten verschiedene Browser.

Der erste Unterschied ist der Unterschied in der Zeit, auf die der Timer für den nächsten Start eingestellt wird. Erstellen wir einen kleinen Test: Wir messen die Zeit, die seit dem Start des vorherigen Laufs und seit seinem Ende vergangen ist.

var d1 = neues Datum(), d2 = neues Datum(); setInterval(function() ( var d = new Date(); document.body.innerHTML += (d - d1) + " " + (d - d2) + "
"; // Setzen Sie eine Markierung am Anfang der Funktion d1 = new Date(); while (new Date() - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

Die Ausgabe ist ab der zweiten Zeile informativ.

In Firefox, Opera, Safari und Chrome ist die Situation ähnlich: Die erste Zahl entspricht ungefähr 1000, die zweite 200 weniger. Der einzige Unterschied wird in der Streuung der Werte liegen. Den geringsten Unterschied gibt es bei Chrome und Opera.

2 Antwort von PunBB (bearbeitet von PunBB 2017.06.08 16:45)

  • Aus: Moskau, Sovkhoznay 3, Apt. 98
  • Eingetragen: 2014.07.08
  • Beiträge: 3,896
  • Likes: 497

Ein weiterer Unterschied, der weniger auffällig und schwieriger zu reproduzieren ist, aber manchmal große Probleme verursachen kann, ist der Widerstand gegen Systemzeitänderungen. Wenn Sie den folgenden Test ausführen

setInterval(function() ( document.body.innerHTML = Math.random(); , 500);

Und nach dem Start stellen Sie die Systemzeit um eine Minute zurück und dann auf Firefox-Browser und Safari wird die Nummernänderung angehalten und nach einer Minute erneut gestartet. Natürlich ist die manuelle Übersetzung der Systemzeit eine äußerst seltene Situation, aber viele Systeme sind so konfiguriert, dass sie die Zeit automatisch mit Servern im Internet synchronisieren, sodass dieser Faktor in manchen Situationen nicht außer Acht gelassen werden kann.

Ein weiterer kleiner Nachteil der setInterval-Funktion besteht darin, dass Sie sich den Bezeichner irgendwo merken müssen, um ihre Aktion stoppen zu können, was nicht immer praktisch ist.

3 Antwort von PunBB

  • Aus: Moskau, Sovkhoznay 3, Apt. 98
  • Eingetragen: 2014.07.08
  • Beiträge: 3,896
  • Likes: 497

Betreff: SetTimeOut und SetInterval, was ist besser in JavaScript zu verwenden?

Um die aufgeführten Nachteile von setInterval zu beseitigen, können Sie mehrere setTimeouts verwenden.

Eine wichtige Alternative zu setInterval ist das rekursive setTimeout:

/** statt: var timerId = setInterval(function() ( alarm("tick"); ), 2000); */ var timerId = setTimeout(function tick() ( alarm("tick"); timerId = setTimeout(tick, 2000); ), 2000);

Im obigen Code wird die nächste Ausführung unmittelbar nach Abschluss der vorherigen Ausführung geplant.

Rekursives setTimeout ist eine flexiblere Timing-Methode als setInterval, da die Zeit bis zur nächsten Ausführung abhängig von den Ergebnissen der aktuellen Ausführung unterschiedlich geplant werden kann.

Wir haben beispielsweise einen Dienst, der alle 5 Sekunden den Server nach neuen Daten abfragt. Wenn der Server überlastet ist, können Sie das Abfrageintervall auf 10, 20, 60 Sekunden erhöhen ... und es dann wieder einstellen, wenn alles wieder normal ist.

Wenn wir regelmäßig CPU-intensive Aufgaben ausführen, können wir den Zeitaufwand für deren Ausführung abschätzen und die nächste Ausführung früher oder später planen.

4 Antwort von PunBB

  • Aus: Moskau, Sovkhoznay 3, Apt. 98
  • Eingetragen: 2014.07.08
  • Beiträge: 3,896
  • Likes: 497

Betreff: SetTimeOut und SetInterval, was ist besser in JavaScript zu verwenden?

Rekursiv setTimeout garantiert eine Pause zwischen Aufrufen, setInterval nicht.

Vergleichen wir die beiden Codes. Der erste verwendet setInterval:

var i = 1; setInterval(function() ( func(i); ), 100);

Der zweite verwendet ein rekursives setTimeout:

var i = 1; setTimeout(function run() ( func(i); setTimeout(run, 100); ), 100);

Mit setInterval wird der interne Timer genau alle 100 ms ausgelöst und func(i) aufgerufen:

Die tatsächliche Pause zwischen Funktionsaufrufen mit setInterval ist kürzer als im Code angegeben!

Das ist natürlich, denn die Betriebszeit der Funktion wird in keiner Weise berücksichtigt, sie „frisst“ einen Teil des Intervalls.

Es ist auch möglich, dass func komplexer war als erwartet und die Ausführung länger als 100 ms dauerte.

In diesem Fall wartet der Interpreter auf den Abschluss der Funktion, überprüft dann den Timer und, wenn die Zeit für den Aufruf von setInterval bereits gekommen (oder verstrichen) ist, erfolgt sofort der nächste Aufruf.

Wenn die Funktion länger als die setInterval-Pause ausgeführt wird, erfolgen die Aufrufe ohne Unterbrechung.

5 Antwort von sempai

  • Aus: Jerusalem
  • Eingetragen: 2015.06.02
  • Beiträge: 958
  • Likes: 274

Betreff: SetTimeOut und SetInterval, was ist besser in JavaScript zu verwenden?

Es hängt alles von der jeweiligen Aufgabe ab. Zunächst wird SetTimeOut verwendet, um den Timer einmal zu starten, und SetInterval wird verwendet, um eine Schleife zu starten. Aber beide Funktionen können verwendet werden, um Skripte zyklisch auszuführen; wenn Sie sie beispielsweise in der SetTimeOut-Funktion rekursiv ausführen, dann verhalten sie sich fast ähnlich wie SetInterval.

Der Nachteil von SetInterval besteht derzeit darin, dass es die Ausführungszeit des Skripts (der Funktion) selbst nicht berücksichtigt. Wenn Sie es beispielsweise für umfangreiche Abfragen verwenden, wird die Intervallzeit erheblich verkürzt kann je nach Browser unterschiedlich sein.

Aber auch hier gilt: Wenn die Funktion oder Anforderung minimiert wird, ist es unwahrscheinlich, dass der Endbenutzer den Unterschied spürt.
Daher muss jeder selbst entscheiden, was er verwendet.



Freunden erzählen