


Zusammenfassung und Weitergabe, um mehrere Schlüsselknoten von NodeJS zu verstehen
Dieser Artikel ist ein persönliches Verständnis von nodejs in der tatsächlichen Entwicklung und beim Lernen. Er ist jetzt zum späteren Nachschlagen zusammengestellt. Es wäre mir eine Ehre, wenn er Sie inspirieren könnte.
Nicht blockierende E/A
E/A: Eingabe/Ausgabe, die Eingabe und Ausgabe eines Systems.
Ein System kann als Individuum verstanden werden, beispielsweise als eine Person. Wenn Sie sprechen, ist es der Output, und wenn Sie zuhören, ist es der Input.
Der Unterschied zwischen blockierender und nicht blockierender E/A besteht darin, ob das System im Zeitraum von der Eingabe bis zur Ausgabe andere Eingaben empfangen kann. Das Folgende sind zwei Beispiele, um zu veranschaulichen, was blockierende I/O und nicht-blockierende I/O sind:
1 Mahlzeiten zubereiten
Zuerst müssen wir den Umfang eines Systems bestimmen. In diesem Beispiel stellt sich die Cafeteria-Tante ein System vor, bei dem der Kellner im Restaurant bestellt und das Essen serviert.
Wenn Sie dann zwischen der Bestellung und dem Servieren von Speisen die Bestellungen anderer Personen annehmen können, können Sie feststellen, ob es sich um blockierende oder nicht blockierende E/A handelt. Für die Cafeteria-Tante kann sie beim Bestellen nicht für andere Schüler bestellen. Erst nachdem der Student die Bestellung abgeschlossen und das Geschirr serviert hat, kann er die Bestellung des nächsten Schülers annehmen, sodass die Cafeteria-Tante den I/O sperrt.
Für den Restaurantkellner kann er den nächsten Gast nach der Bestellung und bevor der Gast das Gericht serviert, bedienen, sodass der Kellner über nicht blockierende E/A verfügt.
2. Hausarbeit erledigenZu diesem Zeitpunkt müssen Sie nicht auf die Waschmaschine warten, sondern können den Schreibtisch und die Kleidung aufräumen Zu diesem Zeitpunkt wird die Wäsche aufgehängt, dann dauert es insgesamt nur 25 Minuten.
Wäsche ist eigentlich ein nicht blockierender I/O. Zwischen dem Einlegen der Kleidung in die Waschmaschine und dem Beenden des Waschvorgangs können Sie andere Dinge tun.
Der Schlüssel zum Verständnis nicht blockierender E/A ist :
Bestimmen Sie eine Systemgrenze
für E/A. Dies ist sehr kritisch, wenn das System wie im obigen Restaurantbeispiel erweitert wird, wenn das System auf das gesamte Restaurant ausgeweitet wird, dann wird der Koch definitiv ein blockierender I/O sein.- Können während des I/O-Prozesses andere I/Os durchgeführt werden?
- NodeJS nicht blockierende E/A
Wie manifestiert sich die nicht blockierende E/A von NodeJS? Wie bereits erwähnt, besteht ein wichtiger Punkt beim Verständnis nicht blockierender E/A darin, zunächst eine Systemgrenze des Knotens zu bestimmen.
Wenn das Architekturdiagramm unten nach Thread-Wartung unterteilt ist, ist die gepunktete Linie links der NodeJS-Thread und die gepunktete Linie rechts der C++-Thread.
Jetzt muss der Nodejs-Thread die Datenbank abfragen. Dies ist ein typischer E/A-Vorgang. Er wird nicht auf die Ergebnisse des E/A-Vorgangs warten und eine große Menge an Daten verteilen Rechenleistung für andere zu berechnende C++-Threads. Warten Sie, bis das Ergebnis ausgegeben wird, und geben Sie es an den NodeJS-Thread zurück. Bevor Sie das Ergebnis erhalten, kann der NodeJS-Thread auch andere E/A-Vorgänge ausführen, sodass er nicht blockiert.entspricht dem linken Teil als Kellner und dem C++-Thread als Chef.
Die nicht blockierende E/A des Knotens wird also durch den Aufruf von C++-Worker-Threads abgeschlossen.Wie benachrichtige ich den NodeJS-Thread, wenn der C++-Thread das Ergebnis erhält? Die Antwort ist
ereignisgesteuert.
EreignisgesteuertBlockierung
: Der Prozess schläft während der E/A und wartet auf den Abschluss der E/A, bevor er mit dem nächsten Schritt fortfährt;
Nicht blockierend: Die Funktion kehrt während der I/O sofort zurück /O, und der Prozess wartet nicht auf den E/A-Abschluss. Um dann das zurückgegebene Ergebnis zu erfahren, müssen Sie den
Ereignistreiberverwenden. Das sogenannte
Ereignisgesteuertekann als das gleiche verstanden werden wie das Front-End-Klickereignis. Ich schreibe zuerst ein Klickereignis, weiß aber nicht, wann es ausgelöst wird. Der Hauptthread führt die ereignisgesteuerte Funktion aus. Dieser Modus ist auch ein Beobachtermodus, das heißt, ich höre mir zuerst das Ereignis an und führe es dann aus, wenn es ausgelöst wird.
Wie implementiert man also Event Drive? Die Antwort ist Asynchrone Programmierung.
Asynchrone ProgrammierungWie oben erwähnt, verfügt NodeJS über eine große Anzahl nicht blockierender E/A, daher müssen die Ergebnisse nicht blockierender E/A über Rückruffunktionen abgerufen werden.
Diese Methode verwendet Rückruffunktionen ist asynchrone Programmierung. Der folgende Code erhält beispielsweise Ergebnisse über eine Rückruffunktion:glob(__dirname+'/**/*', (err, res) => {
result = res
console.log('get result')
})
Spezifikation des Callback-Funktionsformats
Der erste Parameter der NodeJS-Callback-Funktion ist Fehler, und die nachfolgenden Parameter sind das Ergebnis. Warum das tun?
try {
interview(function () {
console.log('smile')
})
} catch(err) {
console.log('cry', err)
}
function interview(callback) {
setTimeout(() => {
if(Math.random() <p>Nach der Ausführung wurde es nicht abgefangen und der Fehler wurde global ausgelöst, was zum Absturz des gesamten NodeJS-Programms führte. </p><p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/image/244/886/980/1657110712466688.png?x-oss-process=image/resize,p_40" class="lazy" title="1657110712466688.png" alt="Zusammenfassung und Weitergabe, um mehrere Schlüsselknoten von NodeJS zu verstehen"></p><p> wird von try Catch nicht erfasst, da setTimeout die Ereignisschleife erneut öffnet. Jedes Mal, wenn eine Ereignisschleife geöffnet wird, wird ein Aufrufstapelkontext neu generiert, der zum Aufrufstapel der vorherigen Ereignisschleife und der Rückruffunktion gehört Wenn setTimeout ausgeführt wird, ist der Aufrufstapel anders. In diesem neuen Aufrufstapel gibt es keinen Try-Catch, daher wird der Fehler global ausgelöst und kann nicht abgefangen werden. Weitere Informationen finden Sie in diesem Artikel. Probleme bei der Verwendung asynchroner Warteschlangen für Try Catch. <a href="https://juejin.cn/post/6995749646366670855" target="_blank" title="https://juejin.cn/post/6995749646366670855"></a>Was sollen wir also tun? Verwenden Sie den Fehler als Parameter: </p><pre class="brush:php;toolbar:false">function interview(callback) {
setTimeout(() => {
if(Math.random() <p> Dies ist jedoch problematischer und muss im Rückruf beurteilt werden, sodass eine ausgereifte Konvention erstellt wird. Der erste Parameter ist err erfolgreich. </p><pre class="brush:php;toolbar:false">function interview(callback) {
setTimeout(() => {
if(Math.random() <p></p>Asynchrone Prozesssteuerung<h3 data-id="heading-5">
<strong></strong>Die Callback-Schreibmethode von NodeJS bringt nicht nur Callback-Bereiche mit sich, sondern auch Probleme mit der asynchronen Prozesssteuerung. </h3><p>Asynchrone Prozesssteuerung bezieht sich hauptsächlich auf die Handhabung der Parallelitätslogik, wenn Parallelität auftritt. Nehmen wir weiterhin das obige Beispiel: Wenn Ihr Kollege zwei Unternehmen interviewt, wird er erst dann von dem dritten Unternehmen interviewt, wenn er erfolgreich zwei Unternehmen interviewt hat. Wie schreibt man diese Logik? Es ist notwendig, jede Variable count:<strong><pre class="brush:php;toolbar:false">var count = 0
interview((err) => {
if (err) {
return
}
count++
if (count >= 2) {
// 处理逻辑
}
})
interview((err) => {
if (err) {
return
}
count++
if (count >= 2) {
// 处理逻辑
}
})
wie die obige Methode zu unterstützen, was sehr mühsam und hässlich ist. Daher erschienen später die Schreibmethoden Promise und Async/Await.
VersprechenDie aktuelle Ereignisschleife kann das Ergebnis nicht abrufen, aber die zukünftige Ereignisschleife wird Ihnen das Ergebnis liefern. Es ist dem sehr ähnlich, was ein Drecksack sagen würde.
Versprechen ist nicht nur ein Drecksack, sondern auch eine Zustandsmaschine:ausstehenderfüllt/gelöst
- abgelehnt
const pro = new Promise((resolve, reject) => { setTimeout(() => { resolve('2') }, 200) }) console.log(pro) // 打印:Promise { <pending> }</pending>
- dann & .catch
gelöstes Zustandsversprechen ruf den ersten später an Ein Versprechen im dann
abgelehnten Zustand ruft den ersten Catch auf.- Jedes Versprechen im Ablehnungszustand, dem nicht .catch folgt, führt zu einem globalen Fehler in der Browser- oder Knotenumgebung. „uncaught“ stellt einen nicht erfassten Fehler dar.
ein neues Versprechen zurückgeben Der Endzustand des Versprechens wird durch die Ausführungsergebnisse der Callback-Funktionen von then und Catch bestimmt:
Wenn die Callback-Funktion immer throw new ist Fehler, das Versprechen ist im Status „Abgelehnt“
Wenn die Rückruffunktion immer zurückkehrt, befindet sich das Versprechen im gelösten Zustand- Aber wenn die Rückruffunktion immer ein Versprechen zurückgibt, stimmt das Versprechen mit dem Versprechensstatus der Rückruffunktion überein
- .
-
function interview() { return new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.5) { resolve('success') } else { reject(new Error('fail')) } }) }) } var promise = interview() var promise1 = promise.then(() => { return new Promise((resolve, reject) => { setTimeout(() => { resolve('accept') }, 400) }) })
Der Status von Versprechen1 wird durch den Status des Gegenzugsversprechens bestimmt, d. h. durch den Status von Versprechen1, nachdem das Gegenzugsversprechen ausgeführt wurde. Was sind die Vorteile davon? Dies kann „das Problem der Rückrufhölle lösen“.var promise = interview() .then(() => { return interview() }) .then(() => { return interview() }) .then(() => { return interview() }) .catch(e => { console.log(e) })
then Wenn der Status des zurückgegebenen Versprechens „Abgelehnt“ ist, wird der erste Catch aufgerufen und der nachfolgende Catch wird nicht aufgerufen. Denken Sie daran: Abgelehnte Anrufe sind der erste Fang, gelöste Anrufe dann der erste.
Versprechen löst asynchrone Prozesssteuerung
Wenn Versprechen nur dazu dienen, Höllenrückrufe zu lösen, ist es zu klein, um Versprechen zu unterschätzen. Die Hauptfunktion von Versprechen besteht darin, asynchrone Prozesssteuerungsprobleme zu lösen. Wenn Sie zwei Unternehmen gleichzeitig interviewen möchten:
function interview() { return new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.5) { resolve('success') } else { reject(new Error('fail')) } }) }) } promise .all([interview(), interview()]) .then(() => { console.log('smile') }) // 如果有一家公司rejected,就catch .catch(() => { console.log('cry') })
async/await
sync/await Was genau ist:
console.log(async function() { return 4 }) console.log(function() { return new Promise((resolve, reject) => { resolve(4) }) })
Die gedruckten Ergebnisse sind die gleichen, das heißt, async/await ist nur der syntaktische Zucker des Versprechens. Wir wissen, dass Try Catch Fehler erfasst,
vom Aufrufstapel abhängt und nur Fehler oberhalb des Aufrufstapels erfassen kann. Wenn Sie jedoch „await“ verwenden, können Sie Fehler in allen Funktionen im Aufrufstapel abfangen. Auch wenn der Fehler in der Aufrufliste einer anderen Ereignisschleife, z. B. setTimeout, ausgegeben wird. Nach der Transformation des Interviewcodes können Sie sehen, dass der Code deutlich optimiert ist.try { await interview(1) await interview(2) await interview(2) } catch(e => { console.log(e) })Was ist, wenn es eine parallele Aufgabe ist?
await Promise.all([interview(1), interview(2)])EreignisschleifeAufgrund der nicht blockierenden E/A von NodeJS müssen Sie einen ereignisgesteuerten Ansatz verwenden, um die E/A-Ergebnisse zu erhalten. Um ereignisgesteuerte Ergebnisse zu erzielen, müssen Sie asynchrone Programmierung verwenden , wie z. B. Rückruffunktionen. Wie führt man diese Rückruffunktionen aus, um die Ergebnisse zu erhalten? Dann müssen Sie eine Ereignisschleife verwenden. Die Ereignisschleife ist die wichtigste Grundlage für die Realisierung der nicht blockierenden E/A-Funktion von nodejs. Nicht blockierende E/A und Ereignisschleife sind beides Funktionen, die von
dieser C++-Bibliothek bereitgestellt werden. 
代码演示:
const eventloop = {
queue: [],
loop() {
while(this.queue.length) {
const callback = this.queue.shift()
callback()
}
setTimeout(this.loop.bind(this), 50)
},
add(callback) {
this.queue.push(callback)
}
}
eventloop.loop()
setTimeout(() => {
eventloop.add(() => {
console.log('1')
})
}, 500)
setTimeout(() => {
eventloop.add(() => {
console.log('2')
})
}, 800)
setTimeout(this.loop.bind(this), 50)
保证了50ms就会去看队列中是否有回调,如果有就去执行。这样就形成了一个事件循环。
当然实际的事件要复杂的多,队列也不止一个,比如有一个文件操作对列,一个时间对列。
const eventloop = {
queue: [],
fsQueue: [],
timerQueue: [],
loop() {
while(this.queue.length) {
const callback = this.queue.shift()
callback()
}
this.fsQueue.forEach(callback => {
if (done) {
callback()
}
})
setTimeout(this.loop.bind(this), 50)
},
add(callback) {
this.queue.push(callback)
}
}
总结
首先我们弄清楚了什么是非阻塞I/O,即遇到I/O立刻跳过执行后面的任务,不会等待I/O的结果。当I/O处理好了之后就会调用我们注册的事件处理函数,这就叫事件驱动。实现事件驱动就必须要用异步编程,异步编程是nodejs中最重要的环节,它从回调函数到promise,最后到async/await(使用同步的方法写异步逻辑)。
更多node相关知识,请访问:nodejs 教程!
setTimeout(this.loop.bind(this), 50)
保证了50ms就会去看队列中是否有回调,如果有就去执行。这样就形成了一个事件循环。Das obige ist der detaillierte Inhalt vonZusammenfassung und Weitergabe, um mehrere Schlüsselknoten von NodeJS zu verstehen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Python und JavaScript haben ihre eigenen Vor- und Nachteile in Bezug auf Gemeinschaft, Bibliotheken und Ressourcen. 1) Die Python-Community ist freundlich und für Anfänger geeignet, aber die Front-End-Entwicklungsressourcen sind nicht so reich wie JavaScript. 2) Python ist leistungsstark in Bibliotheken für Datenwissenschaft und maschinelles Lernen, während JavaScript in Bibliotheken und Front-End-Entwicklungsbibliotheken und Frameworks besser ist. 3) Beide haben reichhaltige Lernressourcen, aber Python eignet sich zum Beginn der offiziellen Dokumente, während JavaScript mit Mdnwebdocs besser ist. Die Wahl sollte auf Projektbedürfnissen und persönlichen Interessen beruhen.

Die Verschiebung von C/C zu JavaScript erfordert die Anpassung an dynamische Typisierung, Müllsammlung und asynchrone Programmierung. 1) C/C ist eine statisch typisierte Sprache, die eine manuelle Speicherverwaltung erfordert, während JavaScript dynamisch eingegeben und die Müllsammlung automatisch verarbeitet wird. 2) C/C muss in den Maschinencode kompiliert werden, während JavaScript eine interpretierte Sprache ist. 3) JavaScript führt Konzepte wie Verschlüsse, Prototypketten und Versprechen ein, die die Flexibilität und asynchrone Programmierfunktionen verbessern.

Unterschiedliche JavaScript -Motoren haben unterschiedliche Auswirkungen beim Analysieren und Ausführen von JavaScript -Code, da sich die Implementierungsprinzipien und Optimierungsstrategien jeder Engine unterscheiden. 1. Lexikalanalyse: Quellcode in die lexikalische Einheit umwandeln. 2. Grammatikanalyse: Erzeugen Sie einen abstrakten Syntaxbaum. 3. Optimierung und Kompilierung: Generieren Sie den Maschinencode über den JIT -Compiler. 4. Führen Sie aus: Führen Sie den Maschinencode aus. V8 Engine optimiert durch sofortige Kompilierung und versteckte Klasse.

Zu den Anwendungen von JavaScript in der realen Welt gehören die serverseitige Programmierung, die Entwicklung mobiler Anwendungen und das Internet der Dinge. Die serverseitige Programmierung wird über node.js realisiert, die für die hohe gleichzeitige Anfrageverarbeitung geeignet sind. 2. Die Entwicklung der mobilen Anwendungen erfolgt durch reaktnative und unterstützt die plattformübergreifende Bereitstellung. 3.. Wird für die Steuerung von IoT-Geräten über die Johnny-Five-Bibliothek verwendet, geeignet für Hardware-Interaktion.

Ich habe eine funktionale SaaS-Anwendung mit mehreren Mandanten (eine EdTech-App) mit Ihrem täglichen Tech-Tool erstellt und Sie können dasselbe tun. Was ist eine SaaS-Anwendung mit mehreren Mietern? Mit Multi-Tenant-SaaS-Anwendungen können Sie mehrere Kunden aus einem Sing bedienen

Dieser Artikel zeigt die Frontend -Integration mit einem Backend, das durch die Genehmigung gesichert ist und eine funktionale edtech SaaS -Anwendung unter Verwendung von Next.js. erstellt. Die Frontend erfasst Benutzerberechtigungen zur Steuerung der UI-Sichtbarkeit und stellt sicher, dass API-Anfragen die Rollenbasis einhalten

JavaScript ist die Kernsprache der modernen Webentwicklung und wird für seine Vielfalt und Flexibilität häufig verwendet. 1) Front-End-Entwicklung: Erstellen Sie dynamische Webseiten und einseitige Anwendungen durch DOM-Operationen und moderne Rahmenbedingungen (wie React, Vue.js, Angular). 2) Serverseitige Entwicklung: Node.js verwendet ein nicht blockierendes E/A-Modell, um hohe Parallelitäts- und Echtzeitanwendungen zu verarbeiten. 3) Entwicklung von Mobil- und Desktop-Anwendungen: Die plattformübergreifende Entwicklung wird durch reaktnative und elektronen zur Verbesserung der Entwicklungseffizienz realisiert.

Zu den neuesten Trends im JavaScript gehören der Aufstieg von Typenkripten, die Popularität moderner Frameworks und Bibliotheken und die Anwendung der WebAssembly. Zukunftsaussichten umfassen leistungsfähigere Typsysteme, die Entwicklung des serverseitigen JavaScript, die Erweiterung der künstlichen Intelligenz und des maschinellen Lernens sowie das Potenzial von IoT und Edge Computing.


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

PHPStorm Mac-Version
Das neueste (2018.2.1) professionelle, integrierte PHP-Entwicklungstool

SublimeText3 Englische Version
Empfohlen: Win-Version, unterstützt Code-Eingabeaufforderungen!

WebStorm-Mac-Version
Nützliche JavaScript-Entwicklungstools

SAP NetWeaver Server-Adapter für Eclipse
Integrieren Sie Eclipse mit dem SAP NetWeaver-Anwendungsserver.

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung