Mehrere Möglichkeiten zur Implementierung eines 0-ms-Verzögerungstimers in js

Mehrere Möglichkeiten zur Implementierung eines 0-ms-Verzögerungstimers in js

Vor zwei Tagen habe ich einen Artikel mit der Einführung „Wie implementiere ich ein rechtzeitiges setTimeout?“ gesehen. 》, der Artikel entstand aus einer Interviewfrage: Gibt es eine Möglichkeit, setTimeout rechtzeitig festzulegen? Weitere Einzelheiten entnehmen Sie bitte Anhang [1]. Nachdem ich ihn gelesen hatte, interessierte ich mich für die Funktion setTimeout und überprüfte die entsprechenden Dokumente auf MDN noch einmal. Darin wurde erwähnt, dass [minimale Verzögerung >= 4 ms], sodass ein 0-ms-Verzögerungstimer nicht mit setTimeout implementiert werden kann. Wenn Sie es implementieren möchten, finden Sie einen Referenzlink [2]. Die Implementierungsidee des Autors besteht darin, es durch postMessage zu simulieren, die Beschränkung von setTimeout zu umgehen und so einen 0-ms-Verzögerungstimer zu implementieren. Kurz gesagt geht es darum, eine Makroaufgabe zu starten, um den Rückruf auszuführen. Sehen wir uns an, wie es implementiert wird:

(Funktion() {
 var Zeitüberschreitungen = [];
 var Nachrichtenname = "Null-Timeout-Nachricht";
 // Wie setTimeout, nimmt aber nur ein Funktionsargument an. Es gibt
 // kein Zeitargument (immer Null) und keine Argumente (Sie müssen einen Abschluss verwenden)
 Funktion setZeroTimeout(fn) {
  Zeitüberschreitungen.push(fn);
  window.postMessage(Nachrichtenname, "*");
 }
 Funktion handleMessage(Ereignis) {
  wenn (Ereignisquelle == Fenster und Ereignisdaten == Nachrichtenname) {
   event.stopPropagation();
   wenn (Timeouts.Länge > 0) {
    var fn = timeouts.shift();
    fn();
   }
  }
 }

 window.addEventListener("Nachricht", handleMessage, true);

 // Fügen Sie das eine Element hinzu, das wir dem Fensterobjekt hinzufügen möchten.
 Fenster.setZeroTimeout = setZeroTimeout;
})();

Der Autor stellt auch eine Demo-Seite zur Verfügung [3]. Ein Vergleich mit setTimeout(0) ergibt folgendes Ausführungsergebnis in meinem Browser:

100 Iterationen von setZeroTimeout dauerten 15 Millisekunden.
100 Iterationen von setTimeout(0) dauerten 488 Millisekunden.

Den Vergleichsergebnissen zufolge wird setZeroTimeout hundertmal schneller ausgeführt als setTimeout, was eine enorme Verbesserung darstellt. Was ich heute besprechen möchte, ist, welche anderen Möglichkeiten es gibt, zusätzlich zur obigen Methode einen 0-ms-Verzögerungstimer zu implementieren. Erstens müssen wir sicherstellen, dass unser benutzerdefinierter Timer asynchron ist, und zweitens, dass er so früh wie möglich ausgeführt wird. Apropos Asynchronität: js bietet mehrere Lösungen, die wir nacheinander überprüfen können.

Bevor wir die verschiedenen Implementierungsmethoden im Detail besprechen, sehen wir uns die von der Vereinbarung bereitgestellte setTimeout-Vergleichsversion wie folgt an. Die Ausführungszeit der benutzerdefinierten Implementierungsschemata wird mit der setTimeout-Version verglichen. Der Code ist relativ einfach:

(Funktion() {
 sei i = 0;
 const start = Date.now();
 Funktion test() {
  wenn(i++ < 100) {
   setzeTimeout(test);
  } anders {
   console.log('setTimeout-Ausführungszeit:', Date.now() - Start);
  }
 }
 setzeTimeout(test);
})();

WarteschlangeMikrotask

Die queueMicrotask-API kann eine Mikrotask hinzufügen. Sie ist relativ einfach zu verwenden. Übergeben Sie einfach eine Rückruffunktion. Die konkrete Implementierung ist wie folgt:

(Funktion() {
 Funktion setZeroTimeout(fn) {
  WarteschlangeMicrotask(fn);
 }
 sei i = 0;
 const start = Date.now();
 Funktion test() {
  wenn(i++ < 100) {
   setZeroTimeout(test);
  } anders {
   console.log('setZeroTimeout-Ausführungszeit:', Date.now() - Start);
  }
 }
 setZeroTimeout(test);
})();

Durch den Vergleich mit der setTimeout-Version sieht das Endergebnis wie folgt aus:

setZeroTimeout Ausführungszeit: 2
setTimeout-Ausführungszeit: 490

Auf MDN gibt es eine ausführliche Einführung zu dieser API, daher werde ich hier nicht näher darauf eingehen. Laut Spezifikationsdokument wird in den meisten Fällen empfohlen, APIs wie requestAnimationFrame() und requestIdleCallback() zu verwenden, da queueMicrotask das Rendering blockiert, was in vielen Fällen keine gute Praxis ist.

asynchron/warten

Async/await ist für Front-End-Entwickler bereits unverzichtbar und wir können es auch hier verwenden, um Folgendes zu erreichen:

(Funktion() {
 asynchrone Funktion setAsyncTimeout(fn) {
  Versprechen.lösen().dann(fn);
 }
 sei i = 0;
 const start = Date.now();
 asynchroner Funktionstest () {
  wenn (i++ < 100) {
   warte auf setAsyncTimeout(Test);
  } anders {
   console.log('setAsyncTimeout-Ausführungszeit:', Date.now() - Start);
  }
 }
 setAsyncTimeout(test);
})();

Durch den Vergleich mit der setTimeout-Version sieht das Endergebnis wie folgt aus:

setAsyncTimeout Ausführungszeit: 2
setTimeout-Ausführungszeit: 490

Wenn Ihnen der Aufwand nichts ausmacht, können Sie auch Promise zur Implementierung verwenden. Tatsächlich sind sie alle ähnlich, nur ein wenig mehr Code, der hier weggelassen wird.

Nachrichtenkanal

MessageChannel ermöglicht uns, einen neuen Nachrichtenkanal zu erstellen und Daten über seine beiden MessagePort-Eigenschaften zu senden. MessageChannel bietet das Konzept von Ports, um die Kommunikation zwischen Ports zu erreichen, z. B. die Kommunikation zwischen Workern/iFrames.

(Funktion() {
 const channel = neuer Nachrichtenkanal();
 Funktion setzeMessageChannelTimeout(fn) {
  channel.port2.postMessage(null);
 }
 channel.port1.onmessage = Funktion() {
    prüfen();
 };
 sei i = 0;
 const start = Date.now();
 Funktion test() {
  wenn(i++ < 100) {
   setzeMessageChannelTimeout(test);
  } anders {
   console.log('setMessageChannelTimeout Ausführungszeit:', Date.now() - Start);
  }
 }
 setzeMessageChannelTimeout(test);
})();

Durch den Vergleich mit der setTimeout-Version sieht das Endergebnis wie folgt aus:

setMessageChannelTimeout Ausführungszeit: 4
setTimeout-Ausführungszeit: 490

Die Ausführung der dritten Methode dauert länger als die beiden vorherigen, da der MessageChannel Makrotasks generiert, während die anderen beiden Methoden Mikrotasks sind. Mikrotasks werden zuerst ausgeführt und blockieren den Hauptthread, sodass sie länger dauern.

endlich

Dieser Artikel bietet drei Implementierungsmethoden, die alle auf der von js bereitgestellten asynchronen Lösung basieren. Die Implementierung selbst ist nicht kompliziert.

Anhang

【1】https://mp.weixin.qq.com/s/QRIXBoKr2dMgLob3Atq9-g
【2】https://dbaron.org/log/20100309-faster-timeouts
【3】https://dbaron.org/mozilla/zero-timeout

Damit ist dieser Artikel über verschiedene Möglichkeiten zur Implementierung eines 0-ms-Verzögerungstimers in js abgeschlossen. Weitere relevante Inhalte zum js-Verzögerungstimer finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung der JavaScript-Timer
  • Details zum JavaScript-Timer
  • JavaScript-Timer zur Realisierung einer zeitlich begrenzten Flash-Sale-Funktion
  • JavaScript-Timer zum nahtlosen Scrollen von Bildern
  • Verwenden des JS-Timers zum Verschieben von Elementen
  • Detaillierte Erklärung des JavaScript-Timer-Prinzips

<<:  Detaillierte Anweisungen zur Installation von SuPHP auf CentOS 7.2

>>:  Grafisches Tutorial zur Installation und Konfiguration von MySQL 8.0.16 unter macOS

Artikel empfehlen

Überwachung sowie Betrieb und Wartung von Linux-Diensten

Inhaltsverzeichnis 1. Installieren Sie das psutil...

So erstellen Sie Ihren eigenen privaten Nexus-Server unter Linux

Dieser Artikel beschreibt, wie man über Docker ei...

Abkürzungszeichen und Akronymzeichen

Die Tags <abbr> und <acronym> stellen ...

Ausführliche Erläuterung des MySQL-Gemeinschaftsindex und des eindeutigen Index

Szenario 1. Pflegen Sie ein Bürgersystem mit eine...

Neue Features in MySQL 8: Unsichtbare Indizes

Hintergrund Indizes sind ein zweischneidiges Schw...

MySQL 8.0.12 Installationskonfigurationsmethode und Kennwortänderung

In diesem Artikel werden die Installations- und K...

Detaillierte Erläuterung der Nginx-Prozessverwaltungs- und Neuladeprinzipien

Prozessstrukturdiagramm Nginx ist eine Multiproze...

Vollständige Liste der CentOS7-Firewall-Betriebsbefehle

Inhaltsverzeichnis Installieren: 1. Grundlegende ...

MySQL-Operator-Zusammenfassung

Inhaltsverzeichnis 1. Arithmetische Operatoren 2....

Mit CSS3 erstellter Hintergrundverlaufsanimationseffekt

Ergebnisse erzielen Implementierungscode html <...

Tutorial zur Installation von Odoo14 aus dem Quellcode unter Ubuntu 18.04

Inhaltsverzeichnis Hintergrund dieser Serie Überb...