Heim Web-Frontend js-Tutorial Analyse des Ereignisschleifenmechanismus von Node.js

Analyse des Ereignisschleifenmechanismus von Node.js

Oct 20, 2018 pm 04:25 PM
es6 javascript node.js

Der Inhalt dieses Artikels befasst sich mit der Analyse des Ereignisschleifenmechanismus von Node.js. Ich hoffe, dass er für Freunde hilfreich ist.

Im Browser-Artikel wurden der Ereignisschleifenmechanismus und einige verwandte Konzepte ausführlich vorgestellt, dies dient jedoch hauptsächlich der Forschung auf der Browserseite. Gilt das auch für die Node-Umgebung? Schauen wir uns zunächst eine Demo an:

setTimeout(()=>{
    console.log('timer1')
    Promise.resolve().then(function() {
        console.log('promise1')
    })}, 0)setTimeout(()=>{
    console.log('timer2')
    Promise.resolve().then(function() {
        console.log('promise2')
    })}, 0)
Nach dem Login kopieren

Kompilieren Sie es mit bloßem Auge und führen Sie es im Browser aus. Sie kennen die Wahrheit bereits, daher werde ich nicht auf Details eingehen.

timer1
promise1
timer2
promise2
Nach dem Login kopieren

Dann führe es unter Node aus, eh. . . Seltsam, das laufende Ergebnis unterscheidet sich vom Browser~

timer1
timer2
promise1
promise2
Nach dem Login kopieren

Das Beispiel zeigt, dass der Ereignisschleifenmechanismus des Browsers und von Node.js unterschiedlich sind, werfen wir einen Blick darauf~

Ereignisverarbeitung von Node.js

Node.js verwendet V8 als Parsing-Engine von js und verwendet eine eigene libuv für die E/A-Verarbeitung. libuv ist eine ereignisgesteuerte plattformübergreifende Abstraktionsschicht, die einige zugrunde liegende Funktionen von kapselt Verschiedene Betriebssysteme stellen eine einheitliche API für die Außenwelt bereit. Der Ereignisschleifenmechanismus ist darin ebenfalls implementiert:

int uv_run(uv_loop_t* loop, uv_run_mode mode) {
  int timeout;
  int r;
  int ran_pending;
  r = uv__loop_alive(loop);
  if (!r)
    uv__update_time(loop);
  while (r != 0 && loop->stop_flag == 0) {
    uv__update_time(loop);
    // timers阶段
    uv__run_timers(loop);
    // I/O callbacks阶段
    ran_pending = uv__run_pending(loop);
    // idle阶段
    uv__run_idle(loop);
    // prepare阶段
    uv__run_prepare(loop);
    timeout = 0;
    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
      timeout = uv_backend_timeout(loop);
    // poll阶段
    uv__io_poll(loop, timeout);
    // check阶段
    uv__run_check(loop);
    // close callbacks阶段
    uv__run_closing_handles(loop);
    if (mode == UV_RUN_ONCE) {
      uv__update_time(loop);
      uv__run_timers(loop);
    }
    r = uv__loop_alive(loop);
    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
      break;
  }
  if (loop->stop_flag != 0)
    loop->stop_flag = 0;
  return r;
}
Nach dem Login kopieren

Laut der offiziellen Einführung von Node.js enthält jede Ereignisschleife 6 Stufen . , entsprechend der Implementierung im libuv-Quellcode, wie in der Abbildung unten gezeigt

Analyse des Ereignisschleifenmechanismus von Node.js

Timer-Stufe: Diese Stufe führt den Rückruf von Timer (setTimeout, setInterval) aus

E/A-Rückrufphase: Führen Sie einige Systemaufruffehler aus, z. B. Netzwerkkommunikationsfehler-Rückrufe

Leerlauf, Vorbereitungsphase: Wird nur intern vom Knoten verwendet

Abfragephase: Neues I abrufen /O-Ereignisse, entsprechend Unter den Bedingungen wird der Knoten hier blockiert

Prüfphase: Führen Sie den Rückruf von setImmediate() aus

Rückrufphase schließen: Führen Sie den Rückruf des Schließereignisses des Sockets aus

Konzentrieren wir uns auf Timer und Umfragen. Überprüfen Sie einfach diese drei Phasen, da die meisten asynchronen Aufgaben in der täglichen Entwicklung in diesen drei Phasen verarbeitet werden.

Timer-Phase

Timer ist die erste Phase der Ereignisschleife, Node Überprüft, ob ein Timer abgelaufen ist, und wenn ja, wird der Rückruf in die Taskwarteschlange des Timers verschoben, um auf die Ausführung zu warten Es gibt keine Garantie dafür, dass der Timer sofort ausgeführt wird, wenn die voreingestellte Zeit erreicht ist, da die Ablaufprüfung des Timers durch den Knoten nicht unbedingt zuverlässig ist. Dies wird von anderen laufenden Programmen auf dem Computer beeinflusst oder der Hauptthread ist nicht inaktiv damals. Im folgenden Code ist beispielsweise die Ausführungsreihenfolge von setTimeout() und setImmediate() ungewiss.

setTimeout(() => {
  console.log('timeout')
  }, 0)
  setImmediate(() => {
  console.log('immediate')
  })
Nach dem Login kopieren

Wenn Sie sie jedoch in einen I/O-Rückruf einfügen, muss setImmediate() zuerst ausgeführt werden, da auf die Abfragephase die Prüfphase folgt.

Umfragephase

Die Umfragephase hat hauptsächlich zwei Funktionen:

Verarbeitung von Ereignissen in der Umfragewarteschlange

Wenn ein Timer abgelaufen ist, Führen Sie seine Rückruffunktion aus.

Die gerade Schleife führt die Rückrufe in der Abfragewarteschlange synchron aus, bis die Warteschlange leer ist oder die ausgeführten Rückrufe die Obergrenze des Systems erreichen (die Obergrenze ist unbekannt). Anschließend prüft die gerade Schleife, ob Es gibt ein voreingestelltes setImmediate(), das in zwei Situationen unterteilt ist:

Wenn es ein voreingestelltes setImmediate() gibt, beendet die Ereignisschleife die Abfragephase, tritt in die Prüfphase ein und führt die Aufgabenwarteschlange der Prüfung aus Phase

Wenn kein voreingestelltes setImmediate() vorhanden ist, blockiert die Ereignisschleife und wartet in dieser Phase

Beachten Sie ein Detail: Kein setImmediate() löst ein Ereignis aus Die Schleife ist in der Poll-Phase blockiert, könnte also der zuvor eingestellte Timer nicht nicht ausgeführt werden? Also, in der Umfragephase Die Schleife verfügt über einen Prüfmechanismus, um zu prüfen, ob die Timer-Warteschlange leer ist. Wenn die Timer-Warteschlange nicht leer ist, wird das Ereignis ausgeführt Die Schleife startet die nächste Runde der Ereignisschleife, d. h. sie tritt erneut in die Timer-Phase ein.

Prüfphase

Der Rückruf von setImmediate() wird zur Prüfwarteschlange hinzugefügt. Aus dem Phasendiagramm der Ereignisschleife können wir erkennen, dass die Ausführungsreihenfolge der Prüfphase nach der Abfrage liegt Phase.

Zusammenfassung

Jede Stufe der Ereignisschleife hat eine Aufgabenwarteschlange

Wenn die Ereignisschleife eine bestimmte Stufe erreicht, wird die Aufgabenwarteschlange dieser Stufe bis zur Warteschlange ausgeführt wird gelöscht. Oder wenn der ausgeführte Rückruf das Systemlimit erreicht, geht er zur nächsten Stufe über

Wenn alle Stufen einmal nacheinander ausgeführt werden, gilt die Ereignisschleife als abgeschlossenes Tick

Das macht Sinn. Aber ohne die Demo verstehe ich es immer noch nicht ganz.

const fs = require('fs')fs.readFile('test.txt', () => {
  console.log('readFile')
  setTimeout(() => {
    console.log('timeout')
  }, 0)
  setImmediate(() => {
    console.log('immediate')
  })
  })
Nach dem Login kopieren

Es sollte kein Zweifel an den Ausführungsergebnissen bestehen

readFile
immediate
timeout
Nach dem Login kopieren

Unterschiede zwischen Node.js und der Browser-Ereignisschleife

Überprüfung des vorherigen Artikels, Mikrotask-Aufgaben in der Browserumgebung Die Warteschlange wird nach der Ausführung jeder Makroaufgabe ausgeführt.

Analyse des Ereignisschleifenmechanismus von Node.js

In Node.js werden Mikrotasks zwischen verschiedenen Phasen der Ereignisschleife ausgeführt, d. h. nach Ausführung einer Phase werden die Aufgaben in der Mikrotask-Warteschlange ausgeführt .

Analyse des Ereignisschleifenmechanismus von Node.js

Demo-Rezension

Bei der Durchsicht der Demo am Anfang des Artikels wird das globale Skript (main()) ausgeführt. und die beiden Timer werden nacheinander in die Timer-Warteschlange gestellt, main() wird ausgeführt, der Aufrufstapel ist inaktiv und die Task-Warteschlange beginnt mit der Ausführung

Analyse des Ereignisschleifenmechanismus von Node.js

首先进入timers阶段,执行timer1的回调函数,打印timer1,并将promise1.then回调放入microtask队列,同样的步骤执行timer2,打印timer2;

至此,timer阶段执行结束,event loop进入下一个阶段之前,执行microtask队列的所有任务,依次打印promise1、promise2。

对比浏览器端的处理过程:

Analyse des Ereignisschleifenmechanismus von Node.js

process.nextTick() VS setImmediate()

In essence, the names should be swapped. process.nextTick() fires more immediately than setImmediate()

来自官方文档有意思的一句话,从语义角度看,setImmediate() 应该比 process.nextTick() 先执行才对,而事实相反,命名是历史原因也很难再变。

process.nextTick() 会在各个事件阶段之间执行,一旦执行,要直到nextTick队列被清空,才会进入到下一个事件阶段,所以如果递归调用 process.nextTick(),会导致出现I/O starving(饥饿)的问题,比如下面例子的readFile已经完成,但它的回调一直无法执行:

const fs = require('fs')const starttime = Date.now()let endtime
fs.readFile('text.txt', () => {
  endtime = Date.now()
  console.log('finish reading time: ', endtime - starttime)})let index = 0function handler () {
  if (index++ >= 1000) return
  console.log(`nextTick ${index}`)
  process.nextTick(handler)
  // console.log(`setImmediate ${index}`)
  // setImmediate(handler)}handler()
Nach dem Login kopieren

process.nextTick()的运行结果:

nextTick 1
nextTick 2
......
nextTick 999
nextTick 1000
finish reading time: 170
Nach dem Login kopieren

替换成setImmediate(),运行结果:

setImmediate 1
setImmediate 2
finish reading time: 80
......
setImmediate 999
setImmediate 1000
Nach dem Login kopieren

这是因为嵌套调用的 setImmediate() 回调,被排到了下一次event loop才执行,所以不会出现阻塞。

总结

1、Node.js 的事件循环分为6个阶段

2、浏览器和Node 环境下,microtask 任务队列的执行时机不同

Node.js中,microtask 在事件循环的各个阶段之间执行

浏览器端,microtask 在事件循环的 macrotask 执行完之后执行

3、递归的调用process.nextTick()会导致I/O starving,官方推荐使用setImmediate()

Das obige ist der detaillierte Inhalt vonAnalyse des Ereignisschleifenmechanismus von Node.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat -Befehle und wie man sie benutzt
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

So implementieren Sie ein Online-Spracherkennungssystem mit WebSocket und JavaScript So implementieren Sie ein Online-Spracherkennungssystem mit WebSocket und JavaScript Dec 17, 2023 pm 02:54 PM

So implementieren Sie mit WebSocket und JavaScript ein Online-Spracherkennungssystem. Einführung: Mit der kontinuierlichen Weiterentwicklung der Technologie ist die Spracherkennungstechnologie zu einem wichtigen Bestandteil des Bereichs der künstlichen Intelligenz geworden. Das auf WebSocket und JavaScript basierende Online-Spracherkennungssystem zeichnet sich durch geringe Latenz, Echtzeit und plattformübergreifende Eigenschaften aus und hat sich zu einer weit verbreiteten Lösung entwickelt. In diesem Artikel wird erläutert, wie Sie mit WebSocket und JavaScript ein Online-Spracherkennungssystem implementieren.

WebSocket und JavaScript: Schlüsseltechnologien zur Implementierung von Echtzeitüberwachungssystemen WebSocket und JavaScript: Schlüsseltechnologien zur Implementierung von Echtzeitüberwachungssystemen Dec 17, 2023 pm 05:30 PM

WebSocket und JavaScript: Schlüsseltechnologien zur Realisierung von Echtzeit-Überwachungssystemen Einführung: Mit der rasanten Entwicklung der Internet-Technologie wurden Echtzeit-Überwachungssysteme in verschiedenen Bereichen weit verbreitet eingesetzt. Eine der Schlüsseltechnologien zur Erzielung einer Echtzeitüberwachung ist die Kombination von WebSocket und JavaScript. In diesem Artikel wird die Anwendung von WebSocket und JavaScript in Echtzeitüberwachungssystemen vorgestellt, Codebeispiele gegeben und deren Implementierungsprinzipien ausführlich erläutert. 1. WebSocket-Technologie

Verwendung von JavaScript und WebSocket zur Implementierung eines Echtzeit-Online-Bestellsystems Verwendung von JavaScript und WebSocket zur Implementierung eines Echtzeit-Online-Bestellsystems Dec 17, 2023 pm 12:09 PM

Einführung in die Verwendung von JavaScript und WebSocket zur Implementierung eines Online-Bestellsystems in Echtzeit: Mit der Popularität des Internets und dem Fortschritt der Technologie haben immer mehr Restaurants damit begonnen, Online-Bestelldienste anzubieten. Um ein Echtzeit-Online-Bestellsystem zu implementieren, können wir JavaScript und WebSocket-Technologie verwenden. WebSocket ist ein Vollduplex-Kommunikationsprotokoll, das auf dem TCP-Protokoll basiert und eine bidirektionale Kommunikation zwischen Client und Server in Echtzeit realisieren kann. Im Echtzeit-Online-Bestellsystem, wenn der Benutzer Gerichte auswählt und eine Bestellung aufgibt

So implementieren Sie ein Online-Reservierungssystem mit WebSocket und JavaScript So implementieren Sie ein Online-Reservierungssystem mit WebSocket und JavaScript Dec 17, 2023 am 09:39 AM

So implementieren Sie ein Online-Reservierungssystem mit WebSocket und JavaScript. Im heutigen digitalen Zeitalter müssen immer mehr Unternehmen und Dienste Online-Reservierungsfunktionen bereitstellen. Es ist von entscheidender Bedeutung, ein effizientes Online-Reservierungssystem in Echtzeit zu implementieren. In diesem Artikel wird erläutert, wie Sie mit WebSocket und JavaScript ein Online-Reservierungssystem implementieren, und es werden spezifische Codebeispiele bereitgestellt. 1. Was ist WebSocket? WebSocket ist eine Vollduplex-Methode für eine einzelne TCP-Verbindung.

JavaScript und WebSocket: Aufbau eines effizienten Echtzeit-Wettervorhersagesystems JavaScript und WebSocket: Aufbau eines effizienten Echtzeit-Wettervorhersagesystems Dec 17, 2023 pm 05:13 PM

JavaScript und WebSocket: Aufbau eines effizienten Echtzeit-Wettervorhersagesystems Einführung: Heutzutage ist die Genauigkeit von Wettervorhersagen für das tägliche Leben und die Entscheidungsfindung von großer Bedeutung. Mit der Weiterentwicklung der Technologie können wir genauere und zuverlässigere Wettervorhersagen liefern, indem wir Wetterdaten in Echtzeit erhalten. In diesem Artikel erfahren Sie, wie Sie mit JavaScript und WebSocket-Technologie ein effizientes Echtzeit-Wettervorhersagesystem aufbauen. In diesem Artikel wird der Implementierungsprozess anhand spezifischer Codebeispiele demonstriert. Wir

So verwenden Sie insertBefore in Javascript So verwenden Sie insertBefore in Javascript Nov 24, 2023 am 11:56 AM

Verwendung: In JavaScript wird die Methode insertBefore() verwendet, um einen neuen Knoten in den DOM-Baum einzufügen. Diese Methode erfordert zwei Parameter: den neuen Knoten, der eingefügt werden soll, und den Referenzknoten (d. h. den Knoten, an dem der neue Knoten eingefügt wird).

Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Jan 05, 2024 pm 06:08 PM

JavaScript-Tutorial: So erhalten Sie HTTP-Statuscode. Es sind spezifische Codebeispiele erforderlich. Vorwort: Bei der Webentwicklung ist häufig die Dateninteraktion mit dem Server erforderlich. Bei der Kommunikation mit dem Server müssen wir häufig den zurückgegebenen HTTP-Statuscode abrufen, um festzustellen, ob der Vorgang erfolgreich ist, und die entsprechende Verarbeitung basierend auf verschiedenen Statuscodes durchführen. In diesem Artikel erfahren Sie, wie Sie mit JavaScript HTTP-Statuscodes abrufen und einige praktische Codebeispiele bereitstellen. Verwenden von XMLHttpRequest

JavaScript und WebSocket: Aufbau eines effizienten Echtzeit-Bildverarbeitungssystems JavaScript und WebSocket: Aufbau eines effizienten Echtzeit-Bildverarbeitungssystems Dec 17, 2023 am 08:41 AM

JavaScript ist eine in der Webentwicklung weit verbreitete Programmiersprache, während WebSocket ein Netzwerkprotokoll für die Echtzeitkommunikation ist. Durch die Kombination der leistungsstarken Funktionen beider können wir ein effizientes Echtzeit-Bildverarbeitungssystem erstellen. In diesem Artikel wird erläutert, wie dieses System mithilfe von JavaScript und WebSocket implementiert wird, und es werden spezifische Codebeispiele bereitgestellt. Zunächst müssen wir die Anforderungen und Ziele des Echtzeit-Bildverarbeitungssystems klären. Angenommen, wir haben ein Kameragerät, das Bilddaten in Echtzeit sammeln kann

See all articles