Heim > Web-Frontend > js-Tutorial > Hauptteil

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

青灯夜游
Freigeben: 2021-11-08 18:30:45
nach vorne
2329 Leute haben es durchsucht

Dieser Artikel wird Ihnen helfen, den Ereignisschleifenmechanismus (Zeitschleife) in Node.js zu verstehen. Ich hoffe, er wird Ihnen hilfreich sein!

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

Heute lernen wir etwas über Ereignisschleifen in NodeJs. Das Verständnis der Ereignisschleife war für mich schon immer eine große Schwierigkeit. Ich hoffe, diese Schwierigkeit durch diesen Blog zu überwinden.

libuv

Bevor Sie die Ereignisschleife lernen, verstehen Sie zunächst die Libuv des Knotens. libuv ist für die Implementierung verschiedener I/O-Modelle auf verschiedenen Betriebssystemen verantwortlich und abstrahiert verschiedene Implementierungen in APIs, die auf Anwendungen von Drittanbietern angewendet werden können.

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

Frage

Bevor wir die Ereignisschleife offiziell lernen, denken wir über eine Frage nach

    setTimeout(() => {
      console.log("timer1");
      Promise.resolve().then(() => {
        console.log("promise1");
      });
    }, 0);

    setTimeout(() => {
      console.log("timer2");
      Promise.resolve().then(() => {
        console.log("promise2");
      });
    }, 0);
Nach dem Login kopieren

Was ist das Ergebnis, wenn dieser Code im Browser ausgeführt wird?

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

Was ist das Ergebnis der Ausführung im Knoten?

Vor Knoten 8.6:

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

Nach Knoten 8.6:

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

Warum es so ein Ergebnis gibt, werden wir später analysieren!

Schauen wir uns zunächst ein Bild an:

Auf dem Bild sind 6 Phasen zu sehen, nämlich: Timer, ausstehende Rückrufe, Leerlauf/Vorbereitung, Umfrage, Prüfung, Rückrufe schließen. Ein Artikel über den Ereignisschleifenmechanismus in Node.js

Timer-Phase: Führt hauptsächlich setTimeOut- und setInterval-Rückrufe aus
  • Ausstehende Rückrufphase: Führt einige Systemaufruffehler aus, z. B. Netzwerkkommunikationsfehler-Rückrufe
  • Leerlauf-/Vorbereitungsphase: Wird nur innerhalb des Systems verwendet (Wir haben keine Kontrolle und Interferenz in dieser Phase)
  • Poll-Phase: Erhalten Sie neue E/A-Ereignisse, z. B. das Erhalten eines E/A-Rückrufs zum Lesen einer Datei.
  • Unter geeigneten Umständen wird NodeJS in dieser Phase blockieren
  • Prüfphase: setImmediate-Rückruf ausführen
  • Zum Beispiel Sokects Destory ausführen, Event-Rückruf schließen
  • Jede Phase folgt einem
  • FIFO
(

Zuerst in first out) Regeln zum Ausführen von Aufgaben in der Aufgabenwarteschlange. Unter diesen sechs Phasen müssen wir uns auf die Phasen „Timer, Umfrage, Überprüfung“ konzentrieren. Die meisten asynchronen Aufgaben in unserer täglichen Entwicklung werden in diesen drei Phasen erledigt. Timer

Lassen Sie uns zunächst über die Timer-Phase sprechen.

timers ist die erste Stufe der Ereignisschleife. Nodejs prüft, ob ein Timer abgelaufen ist, und stellt in diesem Fall seinen Rückruf in die Warteschlange. Allerdings kann nodejs nicht garantieren, dass der Timer den Rückruf sofort ausführt, wenn das voreingestellte Ereignis eintrifft. Dies liegt daran, dass die Ablaufprüfung des Timers durch nodejs nicht unbedingt zuverlässig ist. Dies wird von anderen laufenden Programmen auf dem Computer beeinflusst Begegnung mit dem aktuellen Hauptthread.

Für die Unsicherheit hier gibt die offizielle Website ein Beispiel:

Deklarieren Sie zuerst ein setTimeOut und lesen Sie dann eine Datei extern. Wenn der Dateilesevorgang den Timer überschreitet, stellt der Dateilesevorgang den Timer ein ist verzögert. Dies ist die Situation, in der der Hauptthread nicht inaktiv ist, wie bereits erwähnt.
Umfrage

Die Umfragephase führt hauptsächlich zwei Dinge aus:

1 Verarbeiten Sie die Aufgabenwarteschlange der Umfragephase

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

Im Bild oben können wir auch sehen:

Nachdem die Aufgaben der Poll-Task-Warteschlange in der Poll-Phase ausgeführt wurden, wird geprüft, ob ein voreingestelltes Set vorhanden ist. Wenn nicht, wird in die Prüfphase eingetreten wird hier blockieren.

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

Hier haben wir eine Frage: Wenn es in der Umfragephase blockiert wird, kann der von uns eingestellte Timer dann nicht ausgeführt werden?

TatsächlichWenn die Ereignisschleife in der Abfragephase blockiert wird, verfügt NodeJS über einen Prüfmechanismus. Er prüft, ob die Timer-Warteschlange leer ist, und tritt erneut in die Timer-Phase ein.


check

In der Prüfphase wird hauptsächlich die Rückruffunktion von setImmediate ausgeführt.

小总结

event-loop的每个阶段都有一个队列,当event-loop达到某个阶段之后,将执行这个阶段的任务队列,直到队列清空或者达到系统规定的最大回调限制之后,才会进入下一个阶段。当所有阶段都执行完成一次之后,称event-loop完成一个tick。

案例

上面我们说完了event-loop的理论部分,但是光有理论我们也还是不能很清晰的理解event-loop。下面我们就根据几个demo来更加深入的理解下event-loop!

demo1

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

执行结果:

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

可见执行结果跟我们前面的分析时一致的!

demo2

    const fs = require("fs");
    const EventEmitter = require("events").EventEmitter;
    let pos = 0;
    const messenger = new EventEmitter();

    messenger.on("message", function (msg) {
      console.log(++pos + " message:" + msg); //
    });

    console.log(++pos + " first"); //

    process.nextTick(function () {
      console.log(++pos + " nextTick"); //
    });

    messenger.emit("message", "hello!");
    fs.stat(__filename, function () {
      console.log(++pos + " stat"); //
    });

    setTimeout(function () {
      console.log(++pos + " quick timer"); //
    }, 0);
    setTimeout(function () {
      console.log(++pos + " long timer"); //
    }, 30);
    setImmediate(function () {
      console.log(++pos + " immediate"); //
    });

    console.log(++pos + " last"); //
Nach dem Login kopieren

结果:

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

了解下浏览器和node的event-loop差异在什么地方

在node 8.6 之前:

浏览器中的微任务队列会在每个宏任务执行完成之后执行,而node中的微任务会在事件循环的各个阶段之间执行,即每个阶段执行完成之后会去执行微任务队列。

在8.6之后:

浏览器和node中微任务的执行是一致的!

所以,在文章开头,我们提出的思考的问题就有了结果。

关于 process.nextTick()和setImmediate

process.nextTick()

语法:process.nextTick(callback,agrs)

执行时机:

这个函数其实是独立于 Event Loop 之外的,它有一个自己的队列,当每个阶段完成后,如果存在 nextTick 队列,就会清空队列中的所有回调函数,并且优先于其他 microtask 执行。递归的调用process.nextTick()会导致I/O starving,官方推荐使用setImmediate()

关于starving现象的说明:

    const fs = require("fs");
    fs.readFile("test.txt", (err, msg) => {
      console.log("readFile");
    });

    let index = 0;

    function handler() {
      if (index >= 30) return;
      index++;
      console.log("nextTick" + index);
      process.nextTick(handler);
    }

    handler();
Nach dem Login kopieren

运行结果:

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

可以看到,等到nextTick函数呗执行30次之后,读取文件的回调才被执行!这样的现象被称为 I/O 饥饿

当我们把 process.nextTick 换为 setImmediate

    const fs = require("fs");
    fs.readFile("test.txt", (err, msg) => {
      console.log("readFile");
    });

    let index = 0;

    function handler() {
      if (index >= 30) return;
      index++;
      console.log("nextTick" + index);
      setImmediate(handler);
    }

    handler();
Nach dem Login kopieren

结果:

Ein Artikel über den Ereignisschleifenmechanismus in Node.js

造成这两种差异的原因是,嵌套调用的setImmediate的回调被排到了下一次event-loop中去!

event-loop核心思维导图

1Ein Artikel über den Ereignisschleifenmechanismus in Node.js

结束语

通过今天的学习,让我对event-loop的理解更深刻了。那么,下次见。好好学习,天天向上!

1Ein Artikel über den Ereignisschleifenmechanismus in Node.js

更多编程相关知识,请访问:编程视频!!

Das obige ist der detaillierte Inhalt vonEin Artikel über den Ereignisschleifenmechanismus in Node.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:juejin.cn
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage