2013-07-19 9 views
12

Ich bin neu in Knoten und versuchen, async und Ereignisverhalten Vorteile in Knoten zu verwenden. Ich habe von Knoten alles verstanden, was mit Event-Objekt umgehen, es wird Async-Ausführung sein.
Dann hatte ich versuche dies, folgenden Code betrachten:schreibe asynchrone Funktion mit EventEmitter

var events = require("events"); 

var event = new events.EventEmitter(); 


event.on("work", function() { 

    for (var i = 0; i <= 10; i++) { 
     console.log("I do my work " + i); 
    } 

    event.emit("done"); 
}); 

var async = function (cb) { 

    event.on("done", cb); 
    event.emit("work"); 
    for (var i = 0; i <= 10; i++) { 
     console.log("Async " + i); 
    } 
} 


async(function() { 
    console.log("I am done callback!"); 
}); 

Dies ist Asynchron-Ausführung? Meiner Meinung nach nein! Warum, weil ich diesen Satz gelesen hatte viele:

Ein Ereignis ausgelöst wird, so gehen und etwas tun, und dann, wenn Sie es fertig sind, kommen zurück und sagen Sie mir, aber in der Zwischenzeit werde ich etwas anderes tun.

Wie ein Fast-Food-Restaurant-Szenario. Aber der Code oben, wenn das Ereignis der Arbeit entlassen gehen zu, wird folgende Reihenfolge geschehen:

  1. geht in den Rückruf
  2. lassen durch die Schleife
  3. Ausgang Ich mache meine Arbeit n
  4. gebrannt, um das getan Veranstaltung
  5. Ausgabe Ich bin fertig Callback!
  6. Ausgabe Async n

, warum ich Rückruf fertig bin! gonna Ausgabe vor Async n? Warum ist hier nicht Fast-Food-Restaurant Szenario mag, wie

die Arbeit Ereignis ausgelöst wird, gehen und tun Sie stopfen und kommen zurück, wenn Sie getan, in der Zwischenzeit werde ich Ausgabe Async n

Diese wird verwendet, um über ereignisgesteuertes Verhalten und asynchrone Knoten zu verstehen. Aber jetzt bin ich sehr verwirrt. Ich weiß, Javascript arbeitet an Single-Thread. Wie kann ich eine Async-Funktion mit Event-Emitter schreiben? Aber ich denke, das ist nicht möglich, denn wenn ich ein Ereignis ausspreche, wird es sofort den Handler ausführen.

Antwort

18

Ich habe von Knoten zu verstehen, alles, was mit Event Objekt behandeln, wird es Async-Ausführung sein.

Dies ist falsch. Ereignisse sind synchron. Wenn Sie einen Listener hinzufügen, Sie Speichern nur den Rückruf in einem Objekt:

this._events[type].push(listener); 

Wenn Sie ein Ereignis emittieren, sind Sie nur ein Array iterieren und ruft jeden Zuhörer:

for (i = 0; i < len; i++) 
     listeners[i].apply(this, args); 

Quelle code: https://github.com/joyent/node/blob/master/lib/events.js

Dies ist asynchrone Ausführung? Meiner Meinung nach nein!

Sie haben Recht. Es ist asynchron, wenn Sie eine I/O-Funktion aufrufen oder setImmediate, nextTick oder einen Timer verwenden - sonst ist es synchron.Ein synchroner Code, der asynchron geschrieben wird, konvertiert ihn nicht in einen asynchronen Code.

Warum bin ich Rückruf gemacht! gonna Ausgabe vor Async n?

Denn wenn man die "done" erhalten Rückruf Sie rufen "cb":

event.on("done", cb); 

Wenn cb zurückkehrt, die "Async n" Schleife ausgeführt wird.

Wie kann ich eine Async-Funktion mit Event-Emitter schreiben?

Verwendung setImmediate oder process.nextTick.

Wenn Sie die Schleifenausführung "Ich mache meine Arbeit" aufschieben möchten, können Sie die Zeile events.emit ("work") mit nextTick umbrechen.

var events = require("events"); 

var event = new events.EventEmitter(); 


event.on("work", function() { 

    for (var i = 0; i <= 10; i++) { 
     console.log("I do my work " + i); 
    } 

    event.emit("done"); 
}); 

var async = function (cb) { 

    event.on("done", cb); 
    process.nextTick (function() {   //<----- 
     event.emit("work"); 
    });          //<----- 
    for (var i = 0; i <= 10; i++) { 
     console.log("Async " + i); 
    } 
} 


async(function() { 
    console.log("I am done callback!"); 
}); 

wird dieser Druck:

Async 0 
Async 1 
Async 2 
Async 3 
Async 4 
Async 5 
Async 6 
Async 7 
Async 8 
Async 9 
Async 10 
I do my work 0 
I do my work 1 
I do my work 2 
I do my work 3 
I do my work 4 
I do my work 5 
I do my work 6 
I do my work 7 
I do my work 8 
I do my work 9 
I do my work 10 
I am done callback! 
+0

Die Ereignisschleife wieder ausführen werden, nachdem die Codes in dem Stapel abgeschlossen ist. Zum Beispiel habe ich 3 Zeilen Code. Die erste ist process.nextTick (dosomething) und andere nur console.log ("etwas") ;. Dann wird die Ereignisschleife ausgeführt werden richtig? Und am Anfang dieser Schleife wird der in process.nextTick() registrierte Callback ausgeführt. Recht? –

+0

Blick auf den folgenden Code, wenn ich/test1 aufrufen und in anderen Browser/test2, braucht es eine lange Zeit, um Antwort auf/test2 zu bekommen, für mich ist es wie/test1 block/test2 var express = erfordern ('express'); var app = express(); app.get ('/', Funktion (req, res) { res.send ('Hallo Welt'); }); app.get ('/ Test1', function (REQ, res) { \t \t for (var i = 0; i <= 100000000000; i ++) { \t \t \t } res.send ('The Schleife ist fertig '); }); app.get ('/ test2', Funktion (req, res) { res.send ('Keine Schleife'); }); App.listen (3000); console.log (Express wurde am Port 3000 gestartet); –

+2

/Test1 "blockiert" die Ereignisschleife. Aus diesem Grund ist Node nicht für CPU-intensive Aufgaben geeignet. Sie könnten einen neuen Prozess erstellen und diese Aufgaben erledigen. Lesen Sie diesen Artikel, um die Parallelität im Knoten vollständig zu verstehen: http://neilk.net/blog/2013/04/30/why-you-should-use-nodejs-for-CPU-bound-tasks/ –