Ich verwende Node.js bei der Arbeit und finde es sehr leistungsfähig. Wenn ich gezwungen wäre, ein Wort zu wählen, um Node.js zu beschreiben, würde ich "interessant" sagen (was kein rein positives Adjektiv ist). Die Community ist lebendig und wächst. JavaScript kann trotz seiner Eigenheiten eine großartige Programmiersprache sein. Und Sie werden Ihr eigenes Verständnis von "Best Practice" und den Mustern von gut strukturiertem Code täglich neu überdenken. Es gibt eine enorme Energie an Ideen, die gerade in Node.js einfließen, und die Arbeit mit Node.js setzt Sie all diesem Denken aus - ein großartiges geistiges Gewichtheben.
Node.js in der Produktion ist definitiv möglich, aber weit entfernt von dem "schlüsselfertigen" Einsatz, den die Dokumentation zu versprechen scheint. Mit Node.js v0.6.x wurde "cluster" in die Plattform integriert, was einen der wesentlichen Bausteine darstellt, aber mein "production.js"-Skript besteht immer noch aus ~150 Zeilen Logik, um Dinge wie das Erstellen des Log-Verzeichnisses, das Recyceln toter Worker usw. zu erledigen. Für einen "ernsthaften" Produktionsdienst muss man auch darauf vorbereitet sein, eingehende Verbindungen zu drosseln und all die Dinge zu tun, die Apache für PHP . Um fair zu sein, Ruby on Rails hat dies genau Problem. Es wird durch zwei sich ergänzende Mechanismen gelöst: 1) Ruby on Rails/Node.js hinter einem dedizierten Webserver (in C geschrieben und auf Herz und Nieren getestet) wie Nginx (oder Apache / . ). Der Webserver kann auf effiziente Weise statische Inhalte bereitstellen, auf die Protokollierung zugreifen, URLs umschreiben, die SSL , Zugriffsregeln durchsetzen und mehrere Unterdienste verwalten. Bei Anfragen, die den eigentlichen Node-Service betreffen, leitet der Webserver die Anfrage weiter. 2) Verwendung eines Frameworks wie Einhorn der die Arbeitsprozesse verwaltet, sie regelmäßig recycelt, usw. Ich muss noch ein Node.js Serving-Framework finden, das vollständig ausgereift zu sein scheint. Vielleicht gibt es das, aber ich habe es noch nicht gefunden und verwende immer noch ~150 Zeilen in meiner handgerollten "production.js".
Lesen von Rahmenwerken wie Express macht es den Anschein, als ob die Standardpraxis darin besteht, alles über einen einzigen Node.js-Dienst zu bedienen, der ein Alleskönner ist ... "app.use(express.static(__dirname + '/public'))". Für Dienste mit geringerer Last und für die Entwicklung ist das wahrscheinlich in Ordnung. Aber sobald Sie versuchen, Ihren Dienst in großem Umfang zu belasten und ihn 24/7 laufen zu lassen, werden Sie schnell die Beweggründe entdecken, die große Websites dazu bewegen, gut gebackenen, gehärteten C-Code wie Nginx und alle Anfragen zu statischen Inhalten bearbeiten (...bis Sie eine CDN , wie Amazon CloudFront )). Eine etwas humorvolle und unverblümt negative Sichtweise hierzu finden Sie unter dieser Typ .
Node.js findet auch immer mehr Einsatzmöglichkeiten außerhalb von Dienstleistungen. Selbst wenn Sie etwas anderes für die Bereitstellung von Webinhalten verwenden, können Sie Node.js als Build-Tool einsetzen, indem Sie npm Module, um Ihren Code zu organisieren, Browserify um sie zu einem einzigen Asset zusammenzufügen, und uglify-js um sie für die Bereitstellung zu verkleinern. Für den Umgang mit dem Web ist JavaScript eine perfekte Impedanzanpassung und ist daher häufig der einfachste Weg für einen Angriff. Wenn Sie sich zum Beispiel durch einen Haufen von JSON Antwortnutzlasten, sollten Sie meine Unterstrich-CLI Modul, dem Utility-Belt für strukturierte Daten.
Pro / Kontra:
- Pro: Für einen Server-Typ ist das Schreiben von JavaScript im Backend eine "Einstiegsdroge" in das Erlernen moderner UI-Muster gewesen. Ich fürchte mich nicht mehr vor dem Schreiben von Client-Code.
- Pro: Neigt dazu, eine ordnungsgemäße Fehlerprüfung zu fördern (err wird von praktisch allen Rückrufen zurückgegeben und fordert den Programmierer auf, sich darum zu kümmern; außerdem handhaben async.js und andere Bibliotheken das Paradigma "fehlschlagen, wenn eine dieser Teilaufgaben fehlschlägt" viel besser als typischer synchroner Code)
- Pro: Einige interessante und normalerweise schwierige Aufgaben werden trivial - z. B. die Abfrage des Status von laufenden Aufgaben, die Kommunikation zwischen Arbeitern oder die gemeinsame Nutzung des Cache-Status.
- Pro: Riesige Community und tonnenweise großartige Bibliotheken basierend auf einem soliden Paketmanager (npm)
- Nachteil: JavaScript hat keine Standardbibliothek. Man gewöhnt sich so sehr an den Import von Funktionen, dass es sich seltsam anfühlt, wenn man JSON.parse oder eine andere eingebaute Methode verwendet, die kein npm-Modul erfordert. Das bedeutet, dass es fünf Versionen von allem gibt. Sogar die Module, die im Node.js-Kern" enthalten sind, haben fünf weitere Varianten, falls Sie mit der Standardimplementierung unzufrieden sind. Dies führt zu einer schnellen Entwicklung, aber auch zu einem gewissen Maß an Verwirrung.
Im Vergleich zu einem einfachen Ein-Prozess-pro-Anfrage-Modell ( LAMP ):
- Pro: Skalierbar für Tausende von aktiven Verbindungen. Sehr schnell und sehr effizient. Für eine Webflotte könnte dies eine 10-fache Reduzierung der Anzahl der benötigten Boxen im Vergleich zu PHP oder Ruby bedeuten
- Pro: Das Schreiben paralleler Muster ist einfach. Stellen Sie sich vor, Sie müssen drei (oder N) Blobs von Memcached . Machen Sie das in PHP ... haben Sie gerade einen Code geschrieben, der erst den ersten Blob, dann den zweiten und dann den dritten abruft? Wow, das ist langsam. Es gibt eine spezielle PECL Modul, um dieses spezifische Problem für Memcached zu beheben, aber was ist, wenn Sie einige Memcached-Daten parallel zu Ihrer Datenbankabfrage abrufen wollen? In Node.js ist es aufgrund des asynchronen Paradigmas ganz natürlich, dass eine Webanfrage mehrere Dinge parallel erledigt.
- Nachteil: Asynchroner Code ist grundsätzlich komplexer als synchroner Code, und die Lernkurve kann für Entwickler, die nicht genau wissen, was gleichzeitige Ausführung eigentlich bedeutet, schwierig sein. Dennoch ist es weitaus weniger schwierig als das Schreiben von Multithreading-Code mit Sperren.
- Nachteil: Wenn eine rechenintensive Anfrage z. B. 100 ms lang läuft, wird die Verarbeitung anderer Anfragen, die im selben Node.js-Prozess bearbeitet werden, blockiert ... AKA, kooperatives Multitasking . Dies kann mit dem Web Workers-Muster (Ausgliederung eines Unterprozesses zur Bewältigung der teuren Aufgabe) abgemildert werden. Alternativ könnten Sie eine große Anzahl von Node.js-Workern verwenden und jeden nur eine einzige Anfrage gleichzeitig bearbeiten lassen (immer noch recht effizient, da kein Prozess-Recycling stattfindet).
- Betrug: Der Betrieb eines Produktionssystems ist VIEL komplizierter als ein CGI Modell wie Apache + PHP, Perl , Rubinrot , usw. Unbehandelte Ausnahmen bringen den gesamten Prozess zum Stillstand, so dass die Logik zum Neustart der fehlgeschlagenen Worker erforderlich ist (siehe Cluster ). Module mit fehlerhaftem nativen Code können den Prozess empfindlich stören. Wenn ein Worker stirbt, werden alle von ihm bearbeiteten Anfragen verworfen, so dass eine fehlerhafte API leicht den Dienst für andere gemeinsam gehostete APIs beeinträchtigen kann.
Im Vergleich zum Schreiben eines "echten" Dienstes in Java / C# / C (C? wirklich?)
- Pro: Asynchrones Arbeiten in Node.js ist einfacher als das Arbeiten mit Thread-Safety irgendwo anders und bietet wohl auch größere Vorteile. Node.js ist bei weitem das am wenigsten schmerzhafte asynchrone Paradigma, mit dem ich je gearbeitet habe. Mit guten Bibliotheken ist es nur geringfügig schwieriger als das Schreiben von synchronem Code.
- Pro: Keine Multithreading-/Sperr-Fehler. Es stimmt, Sie müssen im Vorfeld mehr Zeit in das Schreiben von ausführlichem Code investieren, der einen richtigen asynchronen Arbeitsablauf ohne blockierende Operationen ausdrückt. Und man muss einige Tests schreiben und das Ding zum Laufen bringen (es handelt sich um eine Skriptsprache, und das fette Fummeln an Variablennamen wird nur bei Unit-Tests erkannt). ABER, wenn man es einmal zum Laufen gebracht hat, ist die Oberfläche für heisenbugs -- seltsame Probleme, die nur einmal in einer Million Durchläufen auftreten -- die Oberfläche ist einfach viel, viel kleiner. Die Steuern, die beim Schreiben von Node.js-Code anfallen, sind in der Kodierungsphase stark vorbelastet. Dann hat man in der Regel einen stabilen Code.
- Pro: JavaScript ist viel leichter, um Funktionen auszudrücken. Es ist schwer, dies mit Worten zu belegen, aber JSON Dynamische Typisierung, Lambda-Notation, prototypische Vererbung, leichtgewichtige Module, was auch immer ... es braucht einfach weniger Code, um die gleichen Ideen auszudrücken.
- Contra: Vielleicht mögen Sie es wirklich, Dienste in Java zu programmieren?
Eine andere Perspektive auf JavaScript und Node.js finden Sie unter Von Java zu Node.js ein Blogbeitrag über die Eindrücke und Erfahrungen eines Java-Entwicklers beim Erlernen von Node.js.
Module Wenn Sie Node in Betracht ziehen, sollten Sie bedenken, dass die Auswahl der JavaScript-Bibliotheken DEFINE Ihre Erfahrung. Die meisten Leute verwenden mindestens zwei, eine asynchrone Musterhilfe (Step, Futures, Async) und ein JavaScript-Zucker-Modul ( Underscore.js ).
Hilfskraft / JavaScript Zucker:
- Underscore.js - dies verwenden. Tun Sie es einfach. Es macht Ihren Code schön und lesbar mit Sachen wie _.isString(), und _.isArray(). Ich bin mir nicht sicher, wie Sie sonst sicheren Code schreiben könnten. Außerdem, für verbesserte Kommandozeilen-Fu, schauen Sie sich meine eigene Underscore-CLI .
Asynchrone Musterbausteine:
- Schritt - eine sehr elegante Methode, um Kombinationen von seriellen und parallelen Aktionen auszudrücken. Meine persönliche Empfehlung. Siehe meine Stelle wie der Step-Code aussieht.
- Futures - eine viel flexiblere (ist das wirklich gut?) Art und Weise, Bestellungen durch Anforderungen auszudrücken. Man kann Dinge ausdrücken wie "Starte a, b, c parallel. Wenn A und B fertig sind, starte AB. Wenn A und C fertig sind, beginne AC". Eine solche Flexibilität erfordert mehr Sorgfalt, um Fehler in Ihrem Arbeitsablauf zu vermeiden (z. B. nie den Callback aufrufen oder ihn mehrfach aufrufen). Siehe Raynos' Beitrag über die Verwendung von Futures (dies ist der Beitrag, der mich dazu brachte, Futures zu "verstehen").
- Asynchron - eine traditionellere Bibliothek mit einer Methode für jedes Muster. Ich habe damit begonnen, bevor ich zu Step konvertierte und erkannte, dass alle Muster in Async in Step mit einem einzigen, besser lesbaren Paradigma ausgedrückt werden können.
- TameJS - Der von OKCupid geschriebene Precompiler fügt ein neues Sprachprimat "await" hinzu, mit dem sich serielle und parallele Workflows elegant schreiben lassen. Das Muster sieht erstaunlich aus, aber es erfordert eine Vorkompilierung. Ich bin noch dabei, mir eine Meinung zu bilden.
- StreamlineJS - Konkurrent von TameJS. Ich neige zu Tame, aber Sie können sich Ihre eigene Meinung bilden.
Oder lesen Sie alles über die asynchronen Bibliotheken unter dieses Panel-Interview mit den Autoren.
Web-Framework:
- Express Großartiges Ruby on Rails-esk-Framework zum Organisieren von Websites. Es verwendet JADE als XML/HTML-Templating-Engine, die die Erstellung von HTML weit weniger mühsam, ja fast schon elegant macht.
- jQuery Obwohl es sich technisch gesehen nicht um ein Knotenmodul handelt, entwickelt sich jQuery schnell zu einem De-facto-Standard für die clientseitige Benutzeroberfläche. jQuery bietet CSS-ähnliche Selektoren zur "Abfrage" von DOM-Elementen, die dann bearbeitet werden können (Handler, Eigenschaften, Stile usw. festlegen). In die gleiche Richtung geht Twitters Bootstrap CSS-Rahmenwerk, Backbone.js für eine MVC Muster, und Browserify.js um alle Ihre JavaScript-Dateien in einer einzigen Datei zusammenzufassen. Diese Module werden alle zu De-facto-Standards, also sollten Sie sie zumindest ausprobieren, wenn Sie noch nichts von ihnen gehört haben.
Prüfung:
- JSHint - Muss verwendet werden; ich habe dies anfangs nicht verwendet, was jetzt unverständlich erscheint. JSLint fügt eine Reihe von grundlegenden Überprüfungen hinzu, die man bei einer kompilierten Sprache wie Java erhält. Nicht übereinstimmende Klammern, nicht deklarierte Variablen, Typeos in vielen Formen und Größen. Sie können auch verschiedene Formen des so genannten "Anal-Modus" aktivieren, in dem Sie den Stil von Leerzeichen und dergleichen überprüfen, was in Ordnung ist, wenn Sie das mögen - aber der wirkliche Wert liegt darin, dass Sie sofortige Rückmeldung über die genaue Zeilennummer erhalten, in der Sie ein schließendes ")" vergessen haben. ... ohne dass Sie Ihren Code ausführen und die betreffende Zeile finden müssen. "JSHint" ist eine besser konfigurierbare Variante von Douglas Crockford 's JSLint .
- Mokka Konkurrenten zu Vows, das ich allmählich bevorzuge. Beide Frameworks beherrschen die Grundlagen gut genug, aber komplexe Muster lassen sich in Mocha leichter ausdrücken.
- Gelübde Vows ist wirklich sehr elegant. Und es gibt einen schönen Bericht (--spec) aus, der Ihnen zeigt, welche Testfälle bestanden haben und welche nicht. Verbringen Sie 30 Minuten damit, es zu lernen, und Sie können mit minimalem Aufwand grundlegende Tests für Ihre Module erstellen.
- Zombie - Kopflose Tests für HTML und JavaScript mit JSDom als virtueller "Browser". Sehr leistungsstarke Sache. Kombinieren Sie es mit Wiederholen Sie um blitzschnelle deterministische Tests von In-Browser-Code zu erhalten.
- Ein Kommentar dazu, wie man über Prüfungen "nachdenken" kann:
- Testen ist nicht fakultativ. Bei einer dynamischen Sprache wie JavaScript gibt es très einige statische Prüfungen. Die Übergabe von zwei Parametern an eine Methode, die 4 erwartet, führt erst dann zu einem Fehler, wenn der Code ausgeführt wird. Die Messlatte für die Erzeugung von Fehlern in JavaScript ist ziemlich niedrig. Grundlegende Tests sind unerlässlich, um die Überprüfungslücke zu kompilierten Sprachen auszugleichen.
- Vergessen Sie die Validierung, lassen Sie Ihren Code einfach ausführen. Für jede Methode ist mein erster Validierungsfall "nichts bricht", und das ist der Fall, der am häufigsten auftritt. Der Nachweis, dass Ihr Code ohne Fehler läuft, fängt 80 % der Fehler ab und trägt so sehr zur Verbesserung des Vertrauens in Ihren Code bei, dass Sie sich dabei ertappen werden, wie Sie die übersprungenen differenzierten Validierungsfälle wieder hinzufügen.
- Fangen Sie klein an und durchbrechen Sie die Trägheitsbarriere. Wir sind alle faul und stehen unter Zeitdruck, und es ist leicht, Tests als "zusätzliche Arbeit" zu betrachten. Fangen Sie also klein an. Schreiben Sie Testfall 0 - laden Sie Ihr Modul und melden Sie den Erfolg. Wenn Sie sich zwingen, nur so viel zu tun, dann ist die Trägheitsbarriere für das Testen gebrochen. Das sind <30 Minuten beim ersten Mal, einschließlich des Lesens der Dokumentation. Schreiben Sie nun Testfall 1 - rufen Sie eine Ihrer Methoden auf und vergewissern Sie sich, dass "nichts kaputt geht", d.h. dass Sie keinen Fehler zurückbekommen. Für Testfall 1 sollten Sie weniger als eine Minute benötigen. Wenn die Trägheit verschwunden ist, wird es einfach, die Testabdeckung schrittweise zu erweitern.
- Entwickeln Sie nun Ihre Tests mit Ihrem Code weiter. Lassen Sie sich nicht davon einschüchtern, wie der "richtige" End-to-End-Test mit Mock-Servern und so weiter aussehen würde. Der Code fängt einfach an und entwickelt sich weiter, um neue Fälle zu behandeln; das sollten auch die Tests. Wenn Sie neue Fälle und neue Komplexität zu Ihrem Code hinzufügen, fügen Sie Testfälle hinzu, um den neuen Code zu testen. Wenn Sie Fehler finden, fügen Sie Überprüfungen und / oder neue Fälle hinzu, um den fehlerhaften Code abzudecken. Wenn Sie bei der Fehlersuche das Vertrauen in einen Teil des Codes verlieren, gehen Sie zurück und fügen Sie Tests hinzu, um zu beweisen, dass der Code das tut, was Sie glauben, dass er es tut. Erfassen Sie Zeichenketten mit Beispieldaten (von anderen Diensten, die Sie aufrufen, von Websites, die Sie auslesen, was auch immer) und speisen Sie sie in Ihren Parsing-Code ein. Ein paar Fälle hier, eine verbesserte Validierung dort, und Sie erhalten einen äußerst zuverlässigen Code.
Sehen Sie sich auch die offizielles Verzeichnis der empfohlenen Node.js-Module. Allerdings, GitHub's Knotenmodule Wiki ist viel vollständiger und eine gute Quelle.
Um Node zu verstehen, ist es hilfreich, einige der wichtigsten Designentscheidungen zu betrachten:
Node.js ist VERANSTALTUNGSBASIERT y ASYNCHRONOUS / NON-BLOCKING . Ereignisse wie eine eingehende HTTP-Verbindung lösen eine JavaScript-Funktion aus, die ein wenig Arbeit leistet und andere asynchrone Aufgaben wie die Verbindung zu einer Datenbank oder das Abrufen von Inhalten von einem anderen Server in Gang setzt. Sobald diese Aufgaben ausgelöst wurden, wird die Ereignisfunktion beendet und Node.js geht wieder in den Ruhezustand über. Sobald etwas anderes passiert, z. B. die Datenbankverbindung hergestellt wird oder der externe Server mit Inhalten antwortet, werden die Callback-Funktionen ausgelöst und weiterer JavaScript-Code wird ausgeführt, der möglicherweise noch mehr asynchrone Aufgaben (wie eine Datenbankabfrage) auslöst. Auf diese Weise verschachtelt Node.js die Aktivitäten für mehrere parallele Workflows und führt alle Aktivitäten aus, die zu einem bestimmten Zeitpunkt nicht blockiert sind. Das ist der Grund, warum Node.js so gut mit Tausenden von gleichzeitigen Verbindungen zurechtkommt.
Warum verwenden Sie nicht einfach einen Prozess/Thread pro Verbindung wie alle anderen? In Node.js ist eine neue Verbindung nur eine sehr kleine Heap-Zuweisung. Das Starten eines neuen Prozesses benötigt deutlich mehr Speicher, auf manchen Plattformen ein Megabyte. Aber die wirklichen Kosten sind der Overhead, der mit der Kontextumschaltung verbunden ist. Wenn Sie 10^6 Kernel-Threads haben, muss der Kernel eine Menge Arbeit leisten, um herauszufinden, wer als nächstes ausgeführt werden soll. Es wurde viel Arbeit in die Entwicklung eines O(1)-Schedulers für Linux gesteckt, aber am Ende ist es einfach viel effizienter, einen einzigen ereignisgesteuerten Prozess zu haben als 10^6 Prozesse, die um CPU-Zeit konkurrieren. Außerdem verhält sich das Multiprozessmodell unter Überlastbedingungen sehr schlecht und lässt kritische Administrations- und Verwaltungsdienste, insbesondere SSHD, verhungern (was bedeutet, dass man sich nicht einmal in den Rechner einloggen kann, um herauszufinden, wie beschissen er wirklich ist).
Node.js ist MIT EINEM GEWINDE y LOCK FREE . Node.js hat ganz bewusst nur einen einzigen Thread pro Prozess. Aus diesem Grund ist es grundsätzlich unmöglich, dass mehrere Threads gleichzeitig auf Daten zugreifen können. Daher werden keine Sperren benötigt. Threads sind schwierig. Wirklich sehr schwer. Wenn Sie das nicht glauben, haben Sie noch nicht genug Thread-Programmierung betrieben. Sperren richtig einzusetzen ist schwierig und führt zu Fehlern, die wirklich schwer zu finden sind. Durch die Beseitigung von Sperren und Multi-Threading verschwindet eine der schlimmsten Fehlerklassen einfach. Dies könnte der größte Vorteil von Node sein.
Aber wie nutze ich meine 16-Kern-Box?
Zwei Möglichkeiten:
- Für große, rechenintensive Aufgaben wie die Bildkodierung kann Node.js Kindprozesse starten oder Nachrichten an zusätzliche Arbeitsprozesse senden. In diesem Design hätten Sie einen Thread, der den Fluss der Ereignisse verwaltet, und N Prozesse, die schwere Rechenaufgaben erledigen und die anderen 15 CPUs beanspruchen.
- Um den Durchsatz eines Webservices zu skalieren, sollten Sie mehrere Node.js-Server auf einem Rechner laufen lassen, einen pro Kern, unter Verwendung von Cluster (Mit Node.js v0.6.x ersetzt das hier verlinkte offizielle "cluster"-Modul die learnboost-Version, die eine andere API hat). Diese lokalen Node.js-Server können dann auf einem Socket miteinander konkurrieren, um neue Verbindungen zu akzeptieren und die Last auf sie zu verteilen. Sobald eine Verbindung angenommen wird, ist sie fest an einen einzelnen dieser gemeinsamen Prozesse gebunden. In der Theorie hört sich das schlecht an, aber in der Praxis funktioniert es recht gut und erlaubt es, die Kopfschmerzen beim Schreiben von thread-sicherem Code zu vermeiden. Außerdem bedeutet dies, dass Node.js eine ausgezeichnete CPU-Cache-Affinität erhält und die Speicherbandbreite effektiver nutzt.
Mit Node.js können Sie einige wirklich mächtige Dinge tun, ohne ins Schwitzen zu kommen. Nehmen wir an, Sie haben ein Node.js-Programm, das eine Reihe von Aufgaben ausführt und auf eine TCP Port für Befehle, kodiert einige Bilder, was auch immer. Mit fünf Zeilen Code können Sie ein HTTP-basiertes Web-Management-Portal einrichten, das den aktuellen Status der aktiven Aufgaben anzeigt. Dies ist EINFACH zu tun:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(myJavascriptObject.getSomeStatusInfo());
}).listen(1337, "127.0.0.1");
Jetzt können Sie eine URL aufrufen und den Status Ihres laufenden Prozesses überprüfen. Fügen Sie ein paar Schaltflächen hinzu, und Sie haben ein "Verwaltungsportal". Wenn Sie ein laufendes Perl-/Python-/Ruby-Skript haben, ist es nicht gerade einfach, ein "Verwaltungsportal" einzurichten.
Aber ist JavaScript nicht langsam / schlecht / böse / Ausgeburt des Teufels? JavaScript hat einige seltsame Eigenheiten, aber mit den "guten Teilen" ist es eine sehr mächtige Sprache, und auf jeden Fall ist JavaScript DIE Sprache auf dem Client (Browser). JavaScript wird bleiben; andere Sprachen haben es auf die IL abgesehen, und Weltklasse-Talente wetteifern darum, die fortschrittlichsten JavaScript-Engines zu entwickeln. Wegen der Rolle von JavaScript im Browser wird ein enormer technischer Aufwand betrieben, um JavaScript rasend schnell zu machen. V8 ist die neueste und beste Javascript-Engine, zumindest für diesen Monat. Sie übertrifft die anderen Skriptsprachen sowohl in Sachen Effizienz als auch in Sachen Stabilität (ich schaue dich an, Ruby). Und es wird nur besser werden mit riesigen Teams arbeiten an dem Problem bei Microsoft, Google und Mozilla, im Wettbewerb um die beste JavaScript-Engine zu bauen (Es ist nicht mehr ein JavaScript "Interpreter", wie alle modernen Motoren tun Tonnen von JIT Kompilieren unter der Haube mit Interpretation nur als Fallback für Execute-once-Code). Ja, wir alle wünschten, wir könnten ein paar der merkwürdigen JavaScript-Sprachwahlen beheben, aber so schlimm ist es wirklich nicht. Und die Sprache ist so verdammt flexibel, dass man eigentlich nicht JavaScript programmiert, sondern Step oder jQuery - mehr als in jeder anderen Sprache bestimmen in JavaScript die Bibliotheken das Erlebnis. Um Webanwendungen zu erstellen, muss man JavaScript sowieso beherrschen, so dass die Codierung auf dem Server eine Art Synergie der Fähigkeiten darstellt. Es hat mir keine Angst gemacht, Client-Code zu schreiben.
Außerdem, wenn Sie JavaScript WIRKLICH hassen, können Sie syntaktischen Zucker verwenden wie CoffeeScript . Oder alles andere, was JavaScript-Code erzeugt, wie Google Web-Werkzeugkasten (GWT).
Apropos JavaScript: Was ist ein "Abschluss"? - Das ist eine schicke Art zu sagen, dass man lexikalisch skalierte Variablen über Aufrufketten hinweg beibehält. ;) Etwa so:
var myData = "foo";
database.connect( 'user:pass', function myCallback( result ) {
database.query("SELECT * from Foo where id = " + myData);
} );
// Note that doSomethingElse() executes _BEFORE_ "database.query" which is inside a callback
doSomethingElse();
Sehen Sie, wie Sie einfach "myData" verwenden können, ohne etwas Umständliches zu tun, wie es in einem Objekt zu speichern? Und anders als in Java muss die Variable "myData" nicht schreibgeschützt sein. Diese leistungsstarke Spracheigenschaft macht die asynchrone Programmierung viel weniger langwierig und schmerzhaft.
Asynchronen Code zu schreiben wird immer komplexer sein als ein einfaches Single-Thread-Skript zu schreiben, aber mit Node.js ist es nicht viel schwieriger und Sie erhalten eine Menge Vorteile zusätzlich zu der Effizienz und Skalierbarkeit auf Tausende von gleichzeitigen Verbindungen...