Heim >Web-Frontend >js-Tutorial >Nodejs-Studie stellt fest, dass globale Objekte global object_node.js sind

Nodejs-Studie stellt fest, dass globale Objekte global object_node.js sind

WBOY
WBOYOriginal
2016-05-16 16:20:441093Durchsuche

1, Eröffnungsanalyse

Im letzten Kapitel haben wir die grundlegenden theoretischen Kenntnisse von NodeJS erlernt. In den folgenden Kapiteln werden wir die verschiedenen Module entsprechend den offiziellen Dokumenten erlernen Damit der Protagonist dieses Artikels die Bühne betritt, Global

Werfen wir einen Blick auf die offizielle Definition:

Globale ObjekteGlobale ObjekteDiese Objekte sind in allen Modulen verfügbar. Einige dieser Objekte befinden sich nicht tatsächlich im globalen Bereich, sondern im Modulbereich – dies wird vermerkt.

Diese Objekte sind in allen Modulen verfügbar. Tatsächlich befinden sich einige Objekte nicht im globalen Bereich, sondern im Modulbereich – diese werden identifiziert.

In Browsern ist der Bereich der obersten Ebene der globale Bereich. Das bedeutet, dass in Browsern, wenn Sie sich im globalen Bereich befinden,var somethingeine globale Variable definiert wird.

In Node ist dies anders. Der Bereich der obersten Ebene ist nicht der globale Bereich;var somethinginnerhalb eines Node-Moduls ist er lokal für dieses Modul.

Ich denke, jeder sollte mit dem Konzept globaler Objekte vertraut sein. Im Browser ist der Bereich der höchsten Ebene der globale Bereich. Wenn Sie also „var“ verwenden, um eine Variable im globalen Bereich zu definieren, wird diese Variable angezeigt definiert als Global Scope.

Aber in NodeJS ist es anders. Der Geltungsbereich der höchsten Ebene ist nicht der globale Geltungsbereich. Verwenden Sie „var“, um eine Variable in einem Modul zu definieren.

In NodeJS sind in einem Modul definierte Variablen, Funktionen oder Methoden nur innerhalb dieses Moduls verfügbar, sie können jedoch mithilfe des Exportobjekts außerhalb des Moduls übergeben werden.

In Node.js gibt es jedoch immer noch einen globalen Bereich, das heißt, Sie können einige Variablen, Funktionen oder Klassen definieren, die verwendet werden können, ohne dass Module geladen werden müssen.

Gleichzeitig sind auch einige globale Methoden und globale Klassen vordefiniert. Das globale Objekt ist der globale Namespace in NodeJS. Jede globale Variable, Funktion oder jedes Objekt ist ein Attributwert des Objekts.

In der REPL-Laufumgebung können Sie die Details im globalen Objekt mithilfe der folgenden Anweisung beobachten, wie in der folgenden Abbildung dargestellt:

Ich werde im Folgenden nacheinander auf die zugehörigen Attributwertobjekte eingehen, die im globalen Objekt eingebunden sind.

(1), Prozess

Prozess {Objekt} Das Prozessobjekt. Siehe den Abschnitt zum Prozessobjekt.

Prozess-{Objekt} Dies ist ein Prozessobjekt. Ich werde in den folgenden Kapiteln näher darauf eingehen, aber hier möchte ich eine API herausnehmen, um darüber zu sprechen.

Process.nextTick(callback)

Rufen Sie in der nächsten Schleife um die Ereignisschleife diesen Rückruf auf. Dies ist kein einfacher Alias ​​für setTimeout(fn, 0), er ist viel effizienter. Er wird normalerweise ausgeführt, bevor andere E/A-Ereignisse ausgelöst werden, aber es gibt einige Ausnahmen. Siehe Process.maxTickDepth unten.

Rufen Sie die Callback-Callback-Funktion in der nächsten Iteration der Ereignisschleife auf. Dies ist kein einfacher Alias ​​für die Funktion setTimeout(fn, 0), da sie viel effizienter ist.

Diese Funktion kann unsere Rückruffunktion vor jeder E/A aufrufen. Diese Funktion ist für Sie sehr wichtig, wenn Sie einige Vorgänge ausführen möchten, nachdem das Objekt erstellt wurde, aber bevor der E/A-Vorgang erfolgt.

Es gibt viele Leute, die die Verwendung von Process.nextTick() in Node.js nicht verstehen. Schauen wir uns an, was Process.nextTick() ist und wie man es verwendet.

Node.js ist Single-Threaded. Zusätzlich zur System-E/A wird während des Ereignisabfrageprozesses nur ein Ereignis gleichzeitig verarbeitet. Sie können sich die Ereignisabfrage als eine große Warteschlange vorstellen. Zu jedem Zeitpunkt verarbeitet das System nur ein Ereignis.

Auch wenn Ihr Computer über mehrere CPU-Kerne verfügt, können Sie nicht mehrere Ereignisse gleichzeitig parallel verarbeiten. Aufgrund dieser Eigenschaft eignet sich node.js jedoch für die Verarbeitung von E/A-Anwendungen, nicht jedoch für CPU-basierte Computeranwendungen.

In jeder E/A-Anwendung müssen Sie nur eine Rückruffunktion für jeden Ein- und Ausgang definieren, und diese werden automatisch zur Verarbeitungswarteschlange der Ereignisabfrage hinzugefügt.

Wenn der E/A-Vorgang abgeschlossen ist, wird diese Rückruffunktion ausgelöst. Das System wird dann mit der Bearbeitung anderer Anfragen fortfahren.

 

In diesem Verarbeitungsmodus bedeutet „process.nextTick()“, eine Aktion zu definieren und diese Aktion zum nächsten Ereignisabfragezeitpunkt ausführen zu lassen. Schauen wir uns ein Beispiel an. Im Beispiel gibt es ein foo(). Wenn Sie es zum nächsten Zeitpunkt aufrufen möchten, können Sie Folgendes tun:

Code kopieren Der Code lautet wie folgt:

Funktion foo() {
​ console.error('foo');
}

process.nextTick(foo);
console.error('bar');

Führen Sie den obigen Code aus und Sie werden anhand der unten im Terminal gedruckten Informationen sehen, dass die Ausgabe von „bar“ vor „foo“ steht. Dadurch wird die obige Anweisung überprüft. foo() wird zum nächsten Zeitpunkt ausgeführt.

Code kopieren Der Code lautet wie folgt:

bar
foo

Sie können auch die Funktion setTimeout() verwenden, um scheinbar den gleichen Ausführungseffekt zu erzielen:

Code kopieren Der Code lautet wie folgt:

setTimeout(foo, 0);
console.log('bar');

Aber in Bezug auf den internen Verarbeitungsmechanismus unterscheiden sich process.nextTick() und setTimeout(fn, 0) nicht um eine einfache Verzögerung, sondern um mehr Funktionen .

Genauer gesagt erstellt der durch process.nextTick() definierte Aufruf einen neuen Substack. Sie können beliebig viele Operationen auf dem aktuellen Stapel ausführen. Aber sobald netxTick aufgerufen wird, muss die Funktion zum übergeordneten Stapel zurückkehren. Anschließend wartet der Ereignisabfragemechanismus darauf, dass neue Ereignisse erneut verarbeitet werden. Wenn ein Aufruf von nextTick gefunden wird, wird ein neuer Stapel erstellt.

Werfen wir einen Blick darauf, wann wir „process.nextTick()“ verwenden sollten:

CPU-intensive Aufgaben über mehrere Ereignisse hinweg ausführen:

Im folgenden Beispiel gibt es eine „compute()“-Funktion. Wir hoffen, dass diese Funktion so kontinuierlich wie möglich ausgeführt wird, um einige rechenintensive Aufgaben auszuführen.

Gleichzeitig hoffen wir aber auch, dass das System durch diese Funktion nicht blockiert wird, sondern auch auf andere Ereignisse reagieren und diese bewältigen muss. Dieses Anwendungsmodell ähnelt einem Single-Threaded-Webdienstserver. Hier können wir „process.nextTick()“ verwenden, um „compute()“ und die normale Ereignisantwort kreuzweise auszuführen.

Code kopieren Der Code lautet wie folgt:

var http = require('http');
Funktion compute() {
// führt kontinuierlich komplizierte Berechnungen durch
​​// ...
​​process.nextTick(compute);
}
http.createServer(function(req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World');
}).listen(5000, '127.0.0.1');
berechnen();

In diesem Modus müssen wir „compute()“ nicht rekursiv aufrufen. Wir müssen lediglich „process.nextTick()“ in der Ereignisschleife verwenden, um „compute()“ zu definieren, das zum nächsten Zeitpunkt ausgeführt werden soll.

Wenn während dieses Prozesses eine neue HTTP-Anfrage eingeht, verarbeitet der Ereignisschleifenmechanismus zuerst die neue Anfrage und ruft dann compute() auf.

Im Gegenteil, wenn Sie „compute()“ in einen rekursiven Aufruf einfügen, wird das System in „compute()“ immer blockiert und kann keine neuen http-Anfragen verarbeiten. Sie können es selbst versuchen.

Natürlich können wir durch process.nextTick() nicht die tatsächlichen Vorteile der parallelen Ausführung unter mehreren CPUs erzielen. Dadurch wird nur die segmentierte Ausführung derselben Anwendung auf der CPU simuliert.

 (2),Konsole

 console {Object} Wird zum Drucken auf stdout und stderr verwendet. Siehe den Abschnitt stdio.

Konsolen-{Objekt} wird zum Drucken in der Standardausgabe und Fehlerausgabe verwendet. Siehe den Test unten:

 

Code kopieren Der Code lautet wie folgt:

console.log("Hallo Bigbear!") ;
for(var i in der Konsole){
console.log(i " " console[i]) ;
}

Sie erhalten die folgende Ausgabe:

Code kopieren Der Code lautet wie folgt:

var log = function () {
  Process.stdout.write(format.apply(this, arguments) 'n');
}
var info = function () {
  Process.stdout.write(format.apply(this, arguments) 'n');
}
var warn = function () {
  writeError(format.apply(this, arguments) 'n');
}
var error = function () {
  writeError(format.apply(this, arguments) 'n');
}
var dir = Funktion (Objekt) {
  var util = require('util');
  Process.stdout.write(util.inspect(object) 'n');
}
var time = function (label) {
  times[label] = Date.now();
}
var timeEnd = Funktion (Label) {
  var duration = Date.now() - times[label];
  exports.log('undefiniert: NaNms', Label, Dauer);
}
var Trace = Funktion (Label) {
  // TODO kann dies wahrscheinlich besser mit dem Debug-Objekt von V8 machen, wenn das soweit ist
  // ausgesetzt.
  var err = neuer Fehler;
  err.name = 'Trace';
  err.message = Label || '';
  Error.captureStackTrace(err, arguments.callee);
  console.error(err.stack);
}
var behaupten = Funktion (Ausdruck) {
  if (!expression) {
    var arr = Array.prototype.slice.call(arguments, 1);
    require('assert').ok(false, format.apply(this, arr));
  }
}

  通过这些函数,我们基本上知道NodeJS在全局作用域添加了些什么内容,其实Console对象上的相关api只是对Process对象上的„stdout.write“对象上.

 (3),exports与module.exports

   在NodeJS中,有两种作用域,分为全局作用域和模块作用域  

复制代码 代码如下:

var name = 'var-name';
name = 'name';
global.name='globaler-name';
this.name = 'Modulname';
console.log(global.name);
console.log(this.name);
console.log(name);

  我们看到var name = 'var-name';name = 'name'; 是定义的局部变量;

  而global.name='global-name';是为 全局对象定义一个name 属性,

  而 this.name = 'module-name';是为模块对象定义了一个name 属性

  那么我们来验证一下,将下面保存成test2.js,运行

复制代码 代码如下:

var t1 = require('./test1'); 
console.log(t1.name); 
console.log(global.name);

  而 t1.name 则是 test1 模块中通过this.name 定义的,说明this 指向 的是 模块作用域对象.

  exports与module.exports的一点区别

    才是真正的接口,exports只不过是它的一个辅助工具。最终返回给调用的是Module.exports而不是ex Ports.Module.exports

    所有的exports收集到的属性和方法,都赋值给了

。当然,这有个前提,就是Module.exportsModule.exports本身不具备任何属性和方法

    如果,Module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。

  举个栗子:

    新建一个文件 bb.js

复制代码 代码如下:
exports.name = function() {
    console.log('Mein Name ist 大熊 !') ;
} ;

    创建一个测试文件 test.js

  

复制代码 代码如下:
var bb= require('./bb.js');
bb.name(); // 'Mein Name ist 大熊 !'

    修改bb.js如下:

复制代码 代码如下:

module.exports = 'BigBear!' ;
exports.name = function() {
console.log('Mein Name ist Big Bear!') ;
} ;

Referenzieren Sie bb.js und führen Sie es erneut aus

Code kopieren Der Code lautet wie folgt:

var bb= require('./bb.js');
bb.name(); // hat keine Methode 'name'

Es ist ersichtlich, dass Ihr Modul nicht unbedingt ein „instanziiertes Objekt“ zurückgeben muss. Ihr Modul kann jedes zulässige JavaScript-Objekt sein – boolescher Wert, Zahl, Datum, JSON, Zeichenfolge, Funktion, Array usw.

(4), setTimeout, setInterval, process.nextTick, setImmediate

Folgendes erscheint in Form einer Zusammenfassung

Nodejs zeichnet sich durch ereignisgesteuerte, hohe Parallelität aus, die durch asynchrone E/A erzeugt wird. Ereignisse werden in entsprechende Ereignisbeobachter, wie z. B. Leerlaufbeobachter, I/O, eingeteilt. O-Beobachter usw. Jeder Zyklus der Ereignisschleife wird als Tick bezeichnet. Jeder Tick holt Ereignisse der Reihe nach aus dem Ereignisbeobachter und verarbeitet sie.

Der beim Aufruf von setTimeout() oder setInterval() erstellte Timer wird im Rot-Schwarz-Baum im Timer-Beobachter platziert. Bei jedem Ticken prüft er, ob der Timer das Timeout vom Rot-Schwarz-Baum überschritten hat . , wenn es überschritten wird, wird die entsprechende Callback-Funktion sofort ausgeführt. Sowohl setTimeout () als auch setInterval () werden als Timer verwendet. Der Unterschied besteht darin, dass letzterer wiederholt ausgelöst wird. Da die Zeit zu kurz eingestellt ist, wird die Verarbeitung nach dem vorherigen Trigger sofort nach Abschluss der Verarbeitung ausgelöst.

Da der Timer durch Timeout ausgelöst wird, führt dies zu einer verringerten Auslösegenauigkeit. Beispielsweise beträgt das mit setTimeout festgelegte Timeout 5 Sekunden, wenn die Ereignisschleife eine Aufgabe in der 4. Sekunde durchläuft und ihre Ausführungszeit 3 ​​Sekunden beträgt , Dann läuft die Rückruffunktion setTimeout in 2 Sekunden ab, was der Grund für die verringerte Genauigkeit ist. Und weil der Rot-Schwarz-Baum und die Iterationsmethoden zum Speichern von Timern und zum Bestimmen von Auslösern verwendet werden, ist dies eine Leistungsverschwendung.

Alle mit „process.nextTick()“ festgelegten Rückruffunktionen werden im Array platziert und alle werden sofort beim nächsten Tick ausgeführt. Dieser Vorgang ist relativ leichtgewichtig und weist eine hohe Zeitgenauigkeit auf.

Die von setImmediate() festgelegte Callback-Funktion wird auch beim nächsten Tick aufgerufen. Der Unterschied zwischen ihr undprocess.nextTick() liegt in zwei Punkten:

 1. Die Beobachter, zu denen sie gehören, werden mit unterschiedlichen Prioritäten ausgeführt. Process.nextTick() gehört zum Leerlaufbeobachter, setImmediate() gehört zum Prüfbeobachter und die Priorität des Leerlaufs > prüft.

2. Die von setImmediate() festgelegte Rückruffunktion wird in einer verknüpften Liste platziert. Jeder Tick führt nur einen Rückruf in der verknüpften Liste aus. Dadurch soll sichergestellt werden, dass jeder Tick schnell ausgeführt werden kann.

Zweitens: Fassen Sie zusammen

1. Verstehen Sie die Bedeutung der Existenz globaler Objekte

2. Ein kleiner Unterschied zwischen Exports und module.exports

3. Was ist die zugrunde liegende Struktur der Konsole (Kapselung des Prozessobjekts auf hoher Ebene)

4. Der Unterschied zwischen setTimeout, setInterval, process.nextTick und setImmediate

5. Zwei Arten von Bereichen in NodeJS

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