Erlernen das serverseitige JavaScript mit Node.js
() translation by (you can also view the original English article)
Node.js ist im Moment alles, was das Erstellen von Echtzeit-Webanwendungen mit hoher Leistung vereinfacht. Es ermöglicht, dass JavaScript sowohl auf dem Server als auch auf dem Client durchgängig verwendet wird. Dieses Tutorial führt Sie durch die Installation von Node und Ihr erstes "Hello World" -Programm, um einen skalierbaren Twitter-Streaming-Server zu erstellen.
Was ist Node.js?
JavaScript wurde traditionell nur im Webbrowser ausgeführt. In letzter Zeit bestand jedoch großes Interesse daran, es dank des Projekts CommonJS auch auf die Serverseite zu bringen. Andere serverseitige JavaScript-Umgebungen umfassen Jaxer und Narwhal. Node.js unterscheidet sich jedoch ein wenig von diesen Lösungen, da es eher ereignisbasiert als Thread-basiert ist. Webserver wie Apache, die für die Bereitstellung von PHP und anderen CGI-Skripts verwendet werden, sind Thread-basiert, da sie für jede eingehende Anforderung einen System-Thread erzeugen. Während dies für viele Anwendungen in Ordnung ist, lässt sich das Thread-basierte Modell nicht mit vielen langlebigen Verbindungen skalieren, wie Sie dies für die Bereitstellung von Echtzeitanwendungen wie Friendfeed oder Google Wave benötigen würden.
"Jede I/O-Operation in Node.js ist asynchron ..."
Node.js verwendet eine Ereignisschleife anstelle von Threads und kann auf Millionen gleichzeitiger Verbindungen skaliert werden. Es nutzt die Tatsache, dass Server die meiste Zeit auf I/O-Vorgänge warten, beispielsweise das Lesen einer Datei von einer Festplatte, den Zugriff auf einen externen Web-Service oder das Warten auf die Aktualisierung einer Datei, da diese Vorgänge viel langsamer sind als bei Speicheroperationen. Jede I/O-Operation in Node.js ist asynchron. Das bedeutet, dass der Server eingehende Anforderungen weiterhin verarbeiten kann, während die I/O-Operation ausgeführt wird. JavaScript eignet sich hervorragend für die ereignisbasierte Programmierung, da es über anonyme Funktionen und Schließungen verfügt, die das Definieren von Inline-Callbacks zum Kinderspiel machen. Daher wissen JavaScript-Entwickler bereits, wie sie auf diese Weise programmieren. Dieses ereignisbasierte Modell macht Node.js sehr schnell und macht das Skalieren von Echtzeitanwendungen sehr einfach.
Schritt 1 Installation
Node.js läuft auf Unix-basierten Systemen wie Mac OS X, Linux und FreeBSD. Leider wird Windows noch nicht unterstützt. Wenn Sie ein Windows-Benutzer sind, können Sie es unter Ubuntu Linux mit Virtualbox installieren. Folgen Sie dazu diesem Tutorial. Sie müssen das Terminal verwenden, um Node.js zu installieren und auszuführen.
- Laden Sie die neueste Version von Node.js von nodejs.org herunter (die neueste Version zum Zeitpunkt dieses Schreibens ist 0.1.31) und entpacken Sie sie.
- Öffnen Sie das Terminal und führen Sie die folgenden Befehle aus.
1
cd /path/to/nodejs
2
make
3
sudo make install
Viele Meldungen werden an das Terminal ausgegeben, wenn Node.js kompiliert und installiert wird.



Schritt 2 Hallo Welt!
Jede neue Technologie beginnt mit einem "Hallo Welt!" Tutorial, so erstellen wir einen einfachen HTTP-Server, der diese Nachricht bereitstellt. Zunächst müssen Sie jedoch das Modulsystem Node.js verstehen. In Node ist die Funktionalität in Modulen eingeschlossen, die zur Verwendung geladen werden müssen. In der Node.js-Dokumentation sind viele Module aufgeführt. Sie laden diese Module, indem Sie die required
-Funktion wie folgt verwenden:
1 |
|
2 |
var sys = require("sys"); |
Dadurch wird das sys-Modul geladen, das Funktionen enthält, mit denen Aufgaben auf Systemebene wie das Drucken von Ausgaben an das Terminal erledigt werden können. Um eine Funktion in einem Modul zu verwenden, rufen Sie sie für die Variable auf, in der Sie das Modul gespeichert haben, in unserem Fall sys
.
1 |
|
2 |
sys.puts("Hello World!"); |
Das Ausführen dieser beiden Zeilen ist so einfach wie das Ausführen des Befehls node
mit dem Dateinamen der Javascript-Datei als Argument.
1 |
|
2 |
node test.js |
Dies wird "Hello World!" Ausgeben. in der Befehlszeile, wenn ausgeführt.



Um einen HTTP-Server zu erstellen, require
das http
-Modul.
1 |
|
2 |
var sys = require("sys"), |
3 |
http = require("http"); |
4 |
|
5 |
http.createServer(function(request, response) { |
6 |
response.sendHeader(200, {"Content-Type": "text/html"}); |
7 |
response.write("Hello World!"); |
8 |
response.close(); |
9 |
}).listen(8080); |
10 |
|
11 |
sys.puts("Server running at http://localhost:8080/"); |
Dieses Skript importiert die sys
- und http
-Module und erstellt einen HTTP-Server. Die an http.createServer
übergebene anonyme Funktion wird aufgerufen, wenn eine Anforderung an den Server eingeht. Nachdem der Server erstellt wurde, wird der Port 8080 überwacht. Wenn eine Anforderung an den Server eingeht, senden wir zuerst HTTP-Header mit dem Inhaltstyp und dem Statuscode 200 (erfolgreich). Dann schicken wir "Hallo Welt!" und schließen Sie die Verbindung. Sie stellen möglicherweise fest, dass wir die Verbindung explizit schließen müssen. Dies macht es sehr einfach, Daten an den Client zu streamen, ohne die Verbindung zu trennen. Wenn Sie dieses Skript ausführen und in Ihrem Browser http://localhost:8080/
aufrufen, wird "Hello World!" Angezeigt.



Schritt 3 Ein einfacher statischer Dateiserver
OK, also haben wir einen HTTP-Server gebaut, der aber nichts sendet außer "Hello World", egal zu welcher URL Sie gehen. Jeder HTTP-Server muss in der Lage sein, statische Dateien wie HTML-Dateien, Bilder und andere Dateien zu senden. Der folgende Code macht genau das:
1 |
|
2 |
var sys = require("sys"), |
3 |
http = require("http"), |
4 |
url = require("url"), |
5 |
path = require("path"), |
6 |
fs = require("fs"); |
7 |
|
8 |
http.createServer(function(request, response) { |
9 |
var uri = url.parse(request.url).pathname; |
10 |
var filename = path.join(process.cwd(), uri); |
11 |
path.exists(filename, function(exists) { |
12 |
if(!exists) { |
13 |
response.sendHeader(404, {"Content-Type": "text/plain"}); |
14 |
response.write("404 Not Found\n"); |
15 |
response.close(); |
16 |
return; |
17 |
}
|
18 |
|
19 |
fs.readFile(filename, "binary", function(err, file) { |
20 |
if(err) { |
21 |
response.sendHeader(500, {"Content-Type": "text/plain"}); |
22 |
response.write(err + "\n"); |
23 |
response.close(); |
24 |
return; |
25 |
}
|
26 |
|
27 |
response.sendHeader(200); |
28 |
response.write(file, "binary"); |
29 |
response.close(); |
30 |
});
|
31 |
});
|
32 |
}).listen(8080); |
33 |
|
34 |
sys.puts("Server running at http://localhost:8080/"); |
Wir beginnen damit, dass wir alle Module benötigen, die wir in unserem Code benötigen. Dazu gehören die Module sys
, http
, url
, path
und fs
oder das Dateisystem. Als Nächstes erstellen wir einen HTTP-Server wie zuvor. Dieses Mal verwenden wir das url
-Modul, um die eingehende URL der Anfrage zu analysieren und den Pfadnamen der Datei zu finden, auf die zugegriffen wird. Wir finden den tatsächlichen Dateinamen auf der Festplatte des Servers mithilfe von path.join
, der process.cwd()
beitritt, oder das aktuelle Arbeitsverzeichnis mit dem Pfad der angeforderten Datei. Als nächstes prüfen wir, ob die Datei existiert, was eine asynchrone Operation ist und daher einen Rückruf erfordert. Wenn die Datei nicht vorhanden ist, wird eine Nachricht 404 Not Found an den Benutzer gesendet und die Funktion wird zurückgegeben. Ansonsten lesen wir die Datei mit dem Modul fs
mit der "binären" Kodierung und senden die Datei an den Benutzer. Wenn beim Lesen der Datei ein Fehler auftritt, wird dem Benutzer die Fehlermeldung angezeigt und die Verbindung wird geschlossen. Da das alles asynchron ist, kann der Server andere Anforderungen ausführen, während er die Datei von der Festplatte liest, unabhängig davon, wie groß diese ist.
Wenn Sie dieses Beispiel ausführen und zu http://localhost:8080/path/to/file
navigieren, wird diese Datei in Ihrem Browser angezeigt.



Schritt 4 Ein Echtzeit-Tweet-Streamer
Aufbauend auf unserem statischen Dateiserver erstellen wir in Node.js einen Server, der Tweets an einen Client sendet, der über unseren statischen Dateiserver bedient wird. Für den Start benötigen wir in diesem Beispiel ein zusätzliches events
Modul: das Ereignismodul. Node hat ein Konzept namens EventEmitter
, das überall verwendet wird, um Ereignis-Listener für asynchrone Aufgaben abzuwickeln. Ähnlich wie in jQuery oder einem anderen clientseitigen JavaScript-Framework, in dem Sie Ereignis-Listener mit Dingen wie Mausklicks und AJAX-Anforderungen verknüpfen, können Sie mit Event-Listenen Ereignis-Listener an viele Dinge binden, von denen wir einige bereits verwendet haben. Dazu gehören alle I/O-Vorgänge, z. B. Lesen einer Datei, Schreiben einer Datei, Überprüfen, ob eine Datei vorhanden ist, Warten auf HTTP-Anforderungen usw. Der EventEmitter
abstrahiert die Logik des Bindens, Aufhebens und Auslösens solcher Ereignis-Listener. Wir werden einen EventEmitter
verwenden, um die Listener zu benachrichtigen, wenn neue Tweets geladen werden. Wir werden einen EventEmitter verwenden, um die Listener zu benachrichtigen, wenn neue Tweets geladen werden. Die ersten Zeilen unseres Tweet-Streamers importieren alle erforderlichen Module und definieren eine Funktion zum Umgang mit statischen Dateien, die unserem vorherigen Beispiel entnommen wurde.
1 |
|
2 |
var sys = require("sys"), |
3 |
http = require("http"), |
4 |
url = require("url"), |
5 |
path = require("path"), |
6 |
fs = require("fs"), |
7 |
events = require("events"); |
8 |
|
9 |
function load_static_file(uri, response) { |
10 |
var filename = path.join(process.cwd(), uri); |
11 |
path.exists(filename, function(exists) { |
12 |
if(!exists) { |
13 |
response.sendHeader(404, {"Content-Type": "text/plain"}); |
14 |
response.write("404 Not Found\n"); |
15 |
response.close(); |
16 |
return; |
17 |
}
|
18 |
|
19 |
fs.readFile(filename, "binary", function(err, file) { |
20 |
if(err) { |
21 |
response.sendHeader(500, {"Content-Type": "text/plain"}); |
22 |
response.write(err + "\n"); |
23 |
response.close(); |
24 |
return; |
25 |
}
|
26 |
|
27 |
response.sendHeader(200); |
28 |
response.write(file, "binary"); |
29 |
response.close(); |
30 |
});
|
31 |
});
|
32 |
}
|
Wir haben das http
-Modul bereits verwendet, um einen Server zu erstellen. Es ist jedoch auch möglich, einen HTTP-Client mithilfe des Moduls zu erstellen. Wir werden einen HTTP-Client erstellen, um Tweets aus der öffentlichen Zeitleiste von Twitter zu laden, die von der Funktion get_tweets
ausgeführt wird.
1 |
|
2 |
var twitter_client = http.createClient(80, "api.twitter.com"); |
3 |
|
4 |
var tweet_emitter = new events.EventEmitter(); |
5 |
|
6 |
function get_tweets() { |
7 |
var request = twitter_client.request("GET", "/1/statuses/public_timeline.json", {"host": "api.twitter.com"}); |
8 |
|
9 |
request.addListener("response", function(response) { |
10 |
var body = ""; |
11 |
response.addListener("data", function(data) { |
12 |
body += data; |
13 |
});
|
14 |
|
15 |
response.addListener("end", function() { |
16 |
var tweets = JSON.parse(body); |
17 |
if(tweets.length > 0) { |
18 |
tweet_emitter.emit("tweets", tweets); |
19 |
}
|
20 |
});
|
21 |
});
|
22 |
|
23 |
request.close(); |
24 |
}
|
25 |
|
26 |
setInterval(get_tweets, 5000); |
Zuerst erstellen wir einen HTTP-Client an Port 80 für api.twitter.com und erstellen einen neuen EventEmitter
. Die Funktion get_tweets
erstellt eine HTTP-Anforderung "GET" an die öffentliche Zeitleiste von Twitter und fügt einen Ereignis-Listener hinzu, der ausgelöst wird, wenn die Server von Twitter antworten. Da Node.js asynchron ist, werden die Daten im Hauptteil der Antwort in Blöcken angezeigt, die vom Listener "data" der Antwort abgerufen werden. Dieser Listener hängt den Block einfach an die body
-Variable an. Sobald alle Chunks eingegangen sind, wird der Listener "end" ausgelöst und die eingehenden JSON-Daten werden analysiert. Wenn mehr als ein Tweet zurückgegeben wird, emit
wir das "Tweets"-Ereignis auf unserem tweet_emitter
aus und übergeben das Array mit neuen Tweets. Dadurch werden alle Ereignis-Listener ausgelöst, die auf das "Tweets"-Ereignis warten, und die neuen Tweets werden an jeden Client gesendet. Die neuen Tweets erhalten wir alle fünf Sekunden mit setInterval
.
Schließlich müssen wir den HTTP-Server erstellen, um Anfragen zu bearbeiten.
1 |
|
2 |
http.createServer(function(request, response) { |
3 |
var uri = url.parse(request.url).pathname; |
4 |
if(uri === "/stream") { |
5 |
|
6 |
var listener = tweet_emitter.addListener("tweets", function(tweets) { |
7 |
response.sendHeader(200, { "Content-Type" : "text/plain" }); |
8 |
response.write(JSON.stringify(tweets)); |
9 |
response.close(); |
10 |
|
11 |
clearTimeout(timeout); |
12 |
});
|
13 |
|
14 |
var timeout = setTimeout(function() { |
15 |
response.sendHeader(200, { "Content-Type" : "text/plain" }); |
16 |
response.write(JSON.stringify([])); |
17 |
response.close(); |
18 |
|
19 |
tweet_emitter.removeListener(listener); |
20 |
}, 10000); |
21 |
|
22 |
}
|
23 |
else { |
24 |
load_static_file(uri, response); |
25 |
}
|
26 |
}).listen(8080); |
27 |
|
28 |
sys.puts("Server running at http://localhost:8080/"); |
Genau wie bei unserem statischen Dateiserver erstellen wir einen HTTP-Server, der Port 8080 überwacht. Wir analysieren die angeforderte URL. Wenn die URL "/stream"
ist, behandeln wir sie, andernfalls übergeben wir die Anforderung zu unserem statischen Dateiserver. Streaming besteht aus dem Erstellen eines Listeners zum Abhören neuer Tweets auf unserem tweet_emitter
, der durch unsere get_tweets
-Funktion ausgelöst wird. Wir erstellen auch einen Timer, um Anfragen, die länger als 10 Sekunden dauern, zu beenden, indem wir ihnen ein leeres Array senden. Wenn neue Tweets eingehen, senden wir die Tweets als JSON-Daten und löschen den Timer. Sie werden sehen, wie das besser funktioniert, wenn Sie den clientseitigen Code sehen, der sich unten befindet. Speichern Sie es unter dem Namen test.html
im selben Verzeichnis wie das serverseitige JavaScript.
1 |
|
2 |
<!DOCTYPE html>
|
3 |
<html>
|
4 |
<head>
|
5 |
<title>Tweet Streamer</title> |
6 |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> |
7 |
</head>
|
8 |
<body>
|
9 |
<ul id="tweets"></ul> |
10 |
<script type="text/javascript"> |
11 |
var tweet_list = $("#tweets"); |
12 |
|
13 |
function load_tweets() { |
14 |
$.getJSON("/stream", function(tweets) { |
15 |
$.each(tweets, function() { |
16 |
$("<li>").html(this.text).prependTo(tweet_list); |
17 |
});
|
18 |
load_tweets(); |
19 |
});
|
20 |
}
|
21 |
|
22 |
setTimeout(load_tweets, 1000); |
23 |
</script>
|
24 |
</body>
|
25 |
</html>
|
Hier haben wir eine einfache HTML-Seite, die die jQuery-Bibliothek importiert und eine ungeordnete Liste für die Tweets definiert. Unser clientseitiges JavaScript speichert die Tweet-Liste und führt die load_tweets
-Funktion nach einer Sekunde aus. Dies gibt dem Browser genügend Zeit, um das Laden der Seite abzuschließen, bevor die AJAX-Anfrage an den Server gesendet wird. Die load_tweets
-Funktion ist sehr einfach: Sie verwendet die getJSON
-Funktion von jQuery zum Laden /stream
. Wenn eine Antwort eingeht, durchlaufen wir alle Tweets und stellen sie der Tweet-Liste voran. Dann rufen wir erneut load_tweets
auf. Dadurch wird effektiv eine Schleife erstellt, die neue Tweets lädt, die aufgrund des Timeouts auf dem Server nach zehn Sekunden abläuft. Immer wenn neue Tweets vorhanden sind, werden sie an den Client gesendet, der eine ständige Verbindung zum Server aufrechterhält. Diese Technik wird als Long Polling bezeichnet.
Wenn Sie den Server mit node
ausführen und http://localhost:8080/test.html
aufrufen, wird der öffentliche Twitter-Timeline-Stream in Ihrem Browser angezeigt.



Nächste Schritte
Node.js ist eine sehr aufregende Technologie, die das Erstellen von Echtzeit-Anwendungen mit hoher Leistung vereinfacht. Ich hoffe, Sie können den Nutzen erkennen und in einigen Ihrer eigenen Anwendungen verwenden. Aufgrund des großartigen Modulsystems von Node ist es einfach, vorgefertigten Code in Ihrer Anwendung zu verwenden, und für fast alles stehen zahlreiche Module von Drittanbietern zur Verfügung - einschließlich Datenbankverbindungsebenen, Templating-Engines, Mail-Clients und sogar ganze Frameworks, die alle diese Komponenten verbinden Dinge zusammen. Eine vollständige Liste der Module finden Sie im Node.js-Wiki. Weitere Knoten-Tutorials finden Sie unter How To Node. Ich würde auch empfehlen, dass Sie sich ein Video von JSConf ansehen, in dem Ryan Dahl, der Schöpfer von Node, die Design-Philosophie hinter Node beschreibt. Das ist verfügbar.
Ich hoffe, Ihnen hat dieses Tutorial gefallen. Wenn Sie Kommentare haben, können Sie hier einen Kommentar hinterlassen oder mir eine Nachricht auf Twitter senden. Glücklicher Node!