Heim  >  Artikel  >  Web-Frontend  >  Eine kurze Analyse des Funktionsprinzips von require in Node.js_node.js

Eine kurze Analyse des Funktionsprinzips von require in Node.js_node.js

WBOY
WBOYOriginal
2016-05-16 16:43:121339Durchsuche

Fast jeder Node.js-Entwickler kann Ihnen sagen, was die Funktion require() macht, aber wie viele von uns wissen tatsächlich, wie sie funktioniert? Wir verwenden es täglich zum Laden von Bibliotheken und Modulen, aber sein Verhalten ist uns ein Rätsel.

Aus Neugier habe ich mich in den Kerncode des Knotens vertieft, um herauszufinden, was unter der Haube vor sich geht. Aber das ist keine einzelne Funktion. Ich habe module.js im Modulsystem des Knotens gefunden. Diese Datei enthält ein überraschend leistungsstarkes und relativ unbekanntes Kernmodul, das das Laden, Kompilieren und Zwischenspeichern jeder Datei steuert. „require()“ ist nur die Spitze des Eisbergs.

module.js

Code kopieren Der Code lautet wie folgt:

Funktionsmodul (ID, übergeordnetes Element) {
this.id = id;
this.exports = {};
this.parent = parent;
// ...

Module.js spielt innerhalb von Node.js hauptsächlich zwei Rollen. Erstens bietet es eine Grundlage für alle Node.js-Module. Jede Datei ist eine neue Instanz eines Basismoduls, die auch nach der Ausführung der Datei bestehen bleibt. Aus diesem Grund können wir Attribute an module.exports anhängen und sie bei Bedarf zurückgeben.

Die zweite Hauptaufgabe dieses Moduls besteht darin, den Modullademechanismus des Knotens zu verwalten. Die von uns verwendete unabhängige Operationsfunktion „require“ ist eigentlich ein abstraktes Konzept von module.require, das selbst nur eine einfache Kapselung der Funktion Module._load ist. Diese Lademethode übernimmt das eigentliche Laden jeder Datei und beginnt unsere Reise dorthin.

Module._load

Code kopieren Der Code lautet wie folgt:

Module._load = function(request, parent, isMain) {
// 1. Überprüfen Sie Module._cache auf das zwischengespeicherte Modul
// 2. Erstellen Sie eine neue Modulinstanz, wenn der Cache leer ist.
// 3. Speichern Sie es im Cache.
// 4. Rufen Sie module.load() mit dem angegebenen Dateinamen auf.
// Dadurch wird module.compile() aufgerufen, nachdem der Dateiinhalt gelesen wurde.
// 5. Wenn beim Laden/Parsen der Datei ein Fehler aufgetreten ist,
// Das fehlerhafte Modul aus dem Cache löschen
// 6. return module.exports
};

Module._load ist für das Laden neuer Module und die Verwaltung des Modulcaches verantwortlich. Das Zwischenspeichern jedes geladenen Moduls reduziert die Anzahl redundanter Dateilesevorgänge und kann Ihre Anwendung erheblich beschleunigen. Darüber hinaus ermöglichen gemeinsam genutzte Modulinstanzen, dass Singleton-Funktionen von Modulen im Projektstatus verbleiben.

Wenn ein Modul nicht im Cache vorhanden ist, erstellt Module._load ein neues Basismodul dieser Datei. Anschließend weist es das Modul an, den Inhalt der neuen Dateien zu lesen, bevor es sie an module._compile sendet. [1]

Wenn Sie Schritt Nr. 6 oben bemerken, werden Sie sehen, dass module.exports an den Benutzer zurückgegeben wurde. Aus diesem Grund verwenden Sie beim Definieren einer zu verwendenden öffentlichen Schnittstelle exports und module.exports, da Module._load als nächstes den erforderlichen Inhalt zurückgibt. Ich bin überrascht, dass es hier nicht mehr Funktionen gibt, aber es wäre schön, wenn es welche gäbe.

module._compile

Code kopieren Der Code lautet wie folgt:

Module.prototype._compile = function(content, filename) {
// 1. Erstellen Sie die eigenständige Require-Funktion, die module.require.
aufruft // 2. Hängen Sie andere Hilfsmethoden an require.
an // 3. Packt den JS-Code in eine Funktion ein, die unsere Anforderung bereitstellt,
// Modul usw. Variablen lokal im Modulbereich.
// 4. Führen Sie diese Funktion aus
};

· Hier geschieht die wahre Magie. Zunächst wird für dieses Modul eine spezielle eigenständige Require-Funktion erstellt. Dies ist eine Funktion, die wir alle brauchen und mit der wir vertraut sind. Die Funktion selbst ist nur ein Paket in Module.require und enthält auch einige wenig bekannte Hilfsmethoden, die für uns einfach zu verwenden sind:

· require(): Laden Sie ein externes Modul
· require.resolve(): Lösen Sie einen Modulnamen in seinen absoluten Pfad
auf · require.main:Hauptmodul
· require.cache: alle zwischengespeicherten Module
· ·require.extensions: Die verfügbaren Kompilierungsmethoden für jeden gültigen Dateityp entsprechend seiner Erweiterung

Sobald „require“ bereit ist, wird der gesamte geladene Quellcode in einer neuen Funktion gekapselt, die „require“, „module“, „exports“ und alle anderen offengelegten Variablen als Parameter akzeptieren kann. Dies ist eine Funktion, die ausschließlich zur Kapselung des Moduls erstellt wurde, um Konflikte mit der Node.js-Umgebung zu verhindern.

Code kopieren Der Code lautet wie folgt:

(function (exports, require, module, __filename, __dirname) {
// IHR CODE HIER EINGEFÜGT!
});

Die Module._compile-Methode wird synchron ausgeführt, sodass der Aufruf von Module._load nur bis zum Ende dieses Codes warten und module.exprts an den Benutzer zurückgeben kann.

Fazit

Wir haben also den gesamten Anforderungscode verstanden und haben ein vorläufiges Verständnis dafür, wie er funktioniert.

Wenn Sie das alles befolgt haben, sind Sie bereit für das letzte Geheimnis: require('module'). Richtig, das Modulsystem selbst kann über das Modulsystem geladen werden. Beginn. Das mag seltsam klingen, aber es ermöglicht dem Benutzerraum, mit dem Modulladesystem zu interagieren, ohne sich mit dem Kern von Node.j befassen zu müssen. Beliebte Module sind so aufgebaut. [2]

Wenn Sie mehr wissen möchten, schauen Sie sich selbst den Quellcode von module.js an. Es gibt genug Dinge, die Ihnen für eine Weile Kopfschmerzen bereiten. Kann mir der erste sagen, was „NODE_MODULE_CONTEXTS“ ist und warum es hinzugefügt wird und wer es hinzufügt, kann Bonuspunkte erhalten :)

[1] Die Methode module._compile wird nur zum Ausführen von JavaScript-Dateien verwendet. JSON-Dateien müssen über JSON.parse() analysiert und

zurückgegeben werden

[2] Beide Module basieren jedoch auf privaten Modulmethoden wie Module._resolveLookupPaths und Module._findPath. Man könnte meinen, dass es nicht viel besser ist...

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