Heim  >  Artikel  >  Web-Frontend  >  Analyse der Ereignisschleife in Node

Analyse der Ereignisschleife in Node

不言
不言Original
2018-07-20 10:30:001263Durchsuche

Dieser Artikel stellt Ihnen die Analyse der Ereignisschleife in Node vor. Es hat einen gewissen Referenzwert.

Jede Phase in der Ereignisschleife

Der Ereignisschleifenprozess von Node.js ist ungefähr wie folgt:

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

Jede Phase hat ihre eigene Aufgabenwarteschlange Diese Phase: Nachdem alle Warteschlangen ausgeführt wurden oder die maximale Anzahl ausgeführter Aufgaben erreicht wurde, geht es in die nächste Phase.

Timer-Phase

In dieser Phase werden die geplanten Aufgaben ausgeführt, die durch setTimeout und setInterval festgelegt wurden.
Natürlich ist dieses Timing nicht genau, aber nach Überschreiten der Timing-Zeit wird es sofort ausgeführt, sobald die Ausführungsmöglichkeit besteht.

Phase für ausstehende Rückrufe

In dieser Phase werden einige Vorgänge im Zusammenhang mit dem zugrunde liegenden System ausgeführt, z. B. von TCP-Verbindungen zurückgegebene Fehler usw. Wenn diese Fehler auftreten, werden sie von Node auf den nächsten Zyklus verschoben.

Abfragephase

Diese Phase wird verwendet, um Rückrufe im Zusammenhang mit E/A-Vorgängen auszuführen. Der Knoten fragt das Betriebssystem, ob ein neues E/A-Ereignis ausgelöst wurde, und führt dann den entsprechenden Rückruf aus. Fast alle Vorgänge außer den Timer-Ereignissen setImmediate() und close callbacks werden in dieser Phase ausgeführt.

Prüfphase

In dieser Phase werden die von setImmediate() festgelegten Aufgaben ausgeführt.

Rückrufphase schließen

Wenn ein socket oder handle(句柄) plötzlich geschlossen wird, beispielsweise über socket.destroy(), wird in dieser Phase das close-Ereignis ausgegeben.

Spezifische Ausführung der Ereignisschleife

Nachdem die Ereignisschleife initialisiert wurde, wird sie gemäß dem in der Abbildung oben gezeigten Prozess fortgesetzt:

  1. Zuerst wird der Timer in Folge von Aufgaben und pending callback

  2. ausgeführt und dann in die Phasen

    und idle eingetreten, in denen einige Logik innerhalb des Knotens ausgeführt wird; prepare

  3. Dann treten Sie in die

    Umfragephase ein. Zu diesem Zeitpunkt werden alle E/A-Rückrufe ausgeführt, z. B. das Lesen von Dateien, Netzwerkvorgänge usw. Die poll-Stufe verfügt über eine poll-Aufgabenwarteschlange. Der Ausführungsprozess dieser Phase ist wie folgt relativ langwierig: poll queue

  • Beim Eintritt in diese Phase wird zunächst geprüft, ob die

    Timing-Warteschlange ausführbare Aufgaben enthält . Wenn ja, wird zur Ausführung zu timeout gesprungen. 定时器阶段

  • Wenn kein

    vorhanden ist, wird die 定时器任务-Aufgabenwarteschlange überprüft. Wenn sie nicht leer ist, werden alle Aufgaben durchlaufen und ausgeführt, bis sie alle ausgeführt werden Die maximale Anzahl ausführbarer Aufgaben ist erreicht. poll queue

  • Nachdem die Ausführung der Aufgabenwarteschlange abgeschlossen ist, wird geprüft, ob Aufgaben in der Aufgabenwarteschlange poll queue vorhanden sind. Wenn ja, wird die Ereignisschleife zum nächsten < übergehen 🎜> Bühne. setImmediatecheck

  • Wenn es keine
  • -Aufgabe gibt, wartet Node hier auf das Eintreffen neuer IO-Rückrufe und führt diese sofort aus.

    setImmediate

Hinweis

: Diese Wartezeit wird nicht ewig andauern, aber nach Erreichen eines Limits fahren Sie mit der nächsten Stufe zur Ausführung fort.

und

setTimeout()setImmediate()Ein kleines Geheimnis

ist eigentlich kein Geheimnis, aber ich habe es erst nach Prüfung der Informationen erfahren.

Das heißt: Im Knoten wird

in
konvertiert. setTimeout(callback, 0)Weitere Informationen finden Sie hier. Die Ausführungsreihenfolge von setTimeout(callback, 1)

und

setTimeout()setImmediate()Die Ausführungsreihenfolge der folgenden beiden geplanten Aufgaben wird unter verschiedenen Umständen inkonsistent ausgeführt.

setTimeout(function() {
    console.log(&#39;timeout&#39;);
}, 0);

setImmediate(function() {
    console.log(&#39;immediate&#39;);
});

Stellen Sie den Timer im normalen Code ein

Wenn Sie diese beiden geplanten Aufgaben in der normalen Codeausführungsphase festlegen (z. B. im äußersten Codeblock), ist ihre Ausführungsreihenfolge unterschiedlich .

    Zunächst wurde das von uns festgelegte
  1. in

    umgewandelt, sodass beim Eintritt in die setTimeout(callback, 0)-Phase anhand der aktuellen Zeit beurteilt wird, ob die Der Zeitpunkt wurde setTimeout(callback, 1) überschritten. 定时器1ms

  2. Vor dem Eintritt in die Timer-Phase ruft die Ereignisschleife eine Methode auf, um die aktuelle Zeit durch das System zu aktualisieren. Da gleichzeitig andere Programme im System ausgeführt werden, benötigt das System Warten Sie, bis die Prozesse anderer Programme beendet sind. Erhalten Sie die genaue Uhrzeit, daher kann es zu einer gewissen Verzögerung bei der Aktualisierung der Uhrzeit kommen.
  3. Wenn beim Aktualisieren der Zeit keine Verzögerung auftritt und die Zeit kürzer als
  4. ist, wird die Aufgabe

    zuerst ausgeführt erreicht das Limit von 1ms, immediate Die Aufgabe wird zuerst ausgeführt. 1mstimeout

  5. Stellen Sie den Timer im IO-Callback ein

Wenn wir diese beiden Timer im IO-Callback festlegen, wird die

-Aufgabe aus folgenden Gründen zuerst ausgeführt :

  1. 进入 poll phase 轮询阶段之前会先检查是否有 timer 定时任务。

  2. 如果没有 timer 定时任务,才会执行后面的 IO 回调。

  3. 我们在 IO 回调中设置 setTimeout 定时任务,这时已经过了 timer 检查阶段,所以 timer 定时任务会被推迟到下一个循环中执行。

process.nextTick()

无论在事件循环的哪个阶段,只要使用 process.nextTick() 添加了回调任务,Node 都会在进入下一阶段之前把 nextTickQueue 队列中的任务执行完。

setTimeout(function() {
    setImmediate(() => {
        console.log('immediate');
    });
    process.nextTick(() => {
        console.log('nextTick');
    });
}, 0);
// nextTick
// immediate

上述代码中,总是先执行 nextTick 任务,就是因为在循环在进入下一个阶段之前会先执行 nextTickQueue 中的任务。下面代码的执行结果也符合预期。

setImmediate(() => {
    setTimeout(() => {
        console.log('timeout');
    }, 0);
    process.nextTick(() => {
        console.log('nextTick');
    });
});
// nextTick
// timeout

相关推荐:

关于Node异步 I/O的介绍

关于Node模块机制的解析

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

Stellungnahme:
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