Learning Server-Side JavaScript med Node.js

Node.js är allt för tillfället och gör det enkelt att skapa högpresterande webbläsningar i realtid. Det tillåter att JavaScript används till slutet, både på servern och på klienten. Denna handledning kommer att leda dig genom installationen av Node och ditt första "Hello World" -program, för att bygga en skalbar strömmande Twitter-server.

Vad är Node.js?



JavaScript har traditionellt bara körts i webbläsaren, men nyligen har det varit ett stort intresse att få det till serverns sida, tack vare CommonJS-projektet. Andra JavaScript-miljöer på serversidan inkluderar Jaxer och Narwhal. Node.js är dock lite annorlunda från dessa lösningar, eftersom det är händelsebaserat snarare än trådbaserat. Webservrar som Apache som används för att betjäna PHP och andra CGI-skript är trådbaserade eftersom de hämtar en systemgänga för varje inkommande begäran. Även om det här är bra för många applikationer, räcker den trådbaserade modellen inte bra med många långlivade anslutningar som du skulle behöva för att kunna användas i realtidsprogram som Friendfeed eller Google Wave.

"Varje I / O-operation i Node.js är asynkron ..."

Node.js, använder en händelsessling i stället för trådar och kan skala till miljoner samtidiga anslutningar. Det drar nytta av det faktum att servrar tillbringar större delen av sin tid som väntar på I / O-operationer, som att läsa en fil från en hårddisk, få tillgång till en extern webbtjänst eller vänta på att en fil ska slutföras, eftersom dessa operationer är mycket långsammare än i minnesoperationer. Varje I / O-operation i Node.js är asynkron, vilket innebär att servern kan fortsätta att hantera inkommande förfrågningar medan I / O-operationen äger rum. JavaScript är extremt väl lämpat för händelsebaserad programmering eftersom den har anonyma funktioner och stängningar som gör att inline callbacks är en cinch, och JavaScript-utvecklare vet redan hur man programmerar på detta sätt. Den här händelsebaserade modellen gör Node.js väldigt snabbt, och gör det mycket enkelt att göra skalning i realtidsprogram.


Steg 1 Installation

Node.js körs på Unix-baserade system, till exempel Mac OS X, Linux och FreeBSD. Tyvärr är Windows ännu inte stödd, så om du är en Windows-användare kan du installera den på Ubuntu Linux med Virtualbox. För att göra så, följ denna handledning. Du måste använda terminalen för att installera och köra Node.js.

  1. Hämta den senaste versionen av Node.js från nodejs.org (den senaste versionen vid skrivningstidpunkten är 0.1.31) och packa upp den.
  2. Öppna terminalen och kör följande kommandon.
    cd / path / to / nodejs gör sudo make install

    Många meddelanden skickas ut till terminalen när Node.js kompileras och installeras.


Steg 2 Hej världen!

Varje ny teknik börjar med en "Hello World!" handledning, så vi kommer att skapa en enkel HTTP-server som serverar det meddelandet. Först måste du förstå Node.js modulsystem. I Node inkapslas funktionaliteten i moduler som måste laddas för att kunna användas. Det finns många moduler listade i Node.js dokumentationen. Du laddar dessa moduler med hjälp av fordra funktion som så:

 var sys = kräver ("sys");

Detta laddar sys-modulen, som innehåller funktioner för hantering av systemnivåuppgifter som utskrift till terminalen. För att använda en funktion i en modul kallar du den på variabeln som du lagrade modulen i, i vårt fall sys.

 sys.puts ("Hello World!");

Att köra dessa två linjer är lika enkelt som att springa nod kommandot med javascriptfilens filnamn som ett argument.

 node test.js

Detta kommer att mata ut "Hello World!" till kommandoraden vid körning.

För att skapa en HTTP-server måste du fordra de http modul.

 var sys = kräver ("sys"), http = kräver ("http"); http.createServer (funktion (begäran, svar) response.sendHeader (200, "Content-Type": "text / html"); response.write ("Hello World!"); response.close (); ) .listen (8080); sys.puts ("Server körs på http: // localhost: 8080 /");

Detta skript importerar sys och http moduler, och skapar en HTTP-server. Den anonyma funktionen som skickas in http.createServer kommer att ringas närhelst en förfrågan kommer in på servern. När servern är skapad, hörs det att lyssna på port 8080. När en förfrågan till servern kommer in skickar vi först HTTP-rubriker med innehållstyp och statuskod på 200 (lyckad). Då skickar vi "Hello World!" och stäng anslutningen. Du kanske märker att vi måste explicit ansluta anslutningen. Detta gör det väldigt enkelt att strömma data till klienten utan att stänga anslutningen. Om du kör det här skriptet och gå till http: // localhost: 8080 / I din webbläsare kommer du att se "Hello World!"


Steg 3 En enkel statisk filserver

OK, så vi har byggt en HTTP-server, men det skickar inte något förutom "Hello World", oavsett vilken webbadress du går till. Varje HTTP-server måste kunna skicka statiska filer som HTML-filer, bilder och andra filer. Följande kod gör just det:

 var sys = kräver ("sys"), http = kräver ("http"), url = kräver ("url"), sökväg = kräver ("sökväg"), fs = kräver ("fs"); http.createServer (funktion (begäran, svar) var uri = url.parse (request.url). pathname; var filnamn = path.join (process.cwd (), uri); path.exists (filnamn, funktion ) if (! exists) response.sendHeader (404, "Content-Type": "text / plain"); response.write ("404 ej hittat \ n"); response.close (); return;  fs.readFile (filnamn, "binär", funktion (fel, fil) om (err) response.sendHeader (500, "Content-Type": "text / plain"); response.write "answer.write ()"; svara; svara (); return; response.sendHeader (200); response.write (fil, "binär"); response.close (););); 8080); sys.puts ("Server körs på http: // localhost: 8080 /");

Vi börjar med att kräva alla moduler som vi behöver i vår kod. Detta inkluderar sys, http, url, väg, och fs eller filsystem moduler. Nästa skapar vi en HTTP-server som vi gjorde tidigare. Den här gången kommer vi att använda url modul för att analysera inkommande URL för begäran och hitta sökvägen för filen som ska nås. Vi hittar det faktiska filnamnet på serverns hårddisk genom att använda path.join, som går med process.cwd (), eller den aktuella arbetsmappen, med sökvägen till filen som begärs. Därefter kontrollerar vi om filen finns, vilket är en asynkron operation och kräver sålunda en återuppringning. Om filen inte existerar skickas ett 404 Not Found-meddelande till användaren och funktionen returneras. Annars läser vi filen med hjälp av fs modul med hjälp av "binär" kodning och skicka filen till användaren. Om det finns ett fel att läsa filen, presenterar vi felmeddelandet till användaren och stänger anslutningen. Eftersom allt detta är asynkront kan servern betjäna andra förfrågningar medan du läser filen från skivan oavsett hur stor den är.

Om du kör detta exempel och navigera till http: // localhost: 8080 / sökväg / till / fil, den filen visas i din webbläsare.


Steg 4 En Real Time Tweet Streamer

Bygga på vår statiska filserver, vi kommer att bygga en server i Node.js som strömmar tweets till en klient som serveras via vår statiska filserver. För att starta behöver vi en extra modul i det här exemplet: evenemang modul. Node har ett koncept som heter en EventEmitter, som används överallt för att hantera händelsehörare för asynkrona uppgifter. På samma sätt som i jQuery eller en annan JavaScript-ram för klientsidor där du binder händelselysare till saker som musklick och AJAX-förfrågningar, tillåter Node dig att binda händelselysare till många saker, av vilka vi redan har använt. Dessa inkluderar varje I / O-operation, till exempel att läsa en fil, skriva en fil, kontrollera om en fil finns, väntar på HTTP-förfrågningar etc. EventEmitter sammanfattar logiken att binda, binda upp och utlösa sådana händelsehörare. Vi kommer att använda en EventEmitter att meddela lyssnare när nya tweets laddas. De första raderna i vår tweet-streamer importerar alla nödvändiga moduler och definierar en funktion för hantering av statiska filer, vilket togs från vårt tidigare exempel.

 var sys = kräver ("sys"), http = kräver ("http"), url = kräva ("url"), sökväg = kräver ("sökväg"), fs = kräver ("fs"), händelser = kräver "evenemang"); funktion load_static_file (uri, svar) var filnamn = path.join (process.cwd (), uri); path.exists (filnamn, funktion (existerar) if (! exists) response.sendHeader (404, "Content-Type": "text / plain"); response.write ("404 Not Found \ n") ; answer.close (); return; fs.readFile (filnamn, "binär", funktion (fel, fil) om (err) response.sendHeader (500, "Content-Type": "text / plain"  response.write (err + "\ n"); response.close (); return; response.sendHeader (200); response.write (fil, "binär"); response.close ();) ;); 

Vi har använt http modul för att skapa en server tidigare, men det är också möjligt att skapa en HTTP-klient med modulen. Vi kommer att skapa en HTTP-klient för att ladda tweets från Twitter: s offentliga tidslinje, som utförs av get_tweets fungera.

 var twitter_client = http.createClient (80, "api.twitter.com"); var tweet_emitter = nya händelser.EventEmitter (); funktion get_tweets () var request = twitter_client.request ("GET", "/1/statuses/public_timeline.json", "värd": "api.twitter.com"); request.addListener ("svar", funktion (svar) var body = ""; response.addListener ("data", funktion (data) body + = data;); response.addListener ) var tweets = JSON.parse (kropp); om (tweets.length> 0) tweet_emitter.emit ("tweets", tweets););); request.close ();  setInterval (get_tweets, 5000);

Först skapar vi en HTTP-klient på port 80 till api.twitter.com och skapar en ny EventEmitter. De get_tweets funktionen skapar en HTTP "GET" -förfrågan till Twitters offentliga tidslinje och lägger till en händelselysare som kommer att utlösas när Twitter-servrar svarar. Eftersom Node.js är asynkron, kommer data i svarkroppen i bitar, som tas upp av svarets "data" -listor. Denna lyssnare lägger helt enkelt chunken till kropp variabel. När alla bitarna har kommit in, utlöses "slut" lyssnaren och vi analyserar inkommande JSON-data. Om mer än en tweet returneras, vi avge "tweets" -evenemanget på vår tweet_emitter, och passera i rad nya tweets. Detta kommer att utlösa alla händelselyttare som lyssnar på "tweets" -händelsen och skicka de nya tweetsna till varje klient. Vi återupptar de nya tweetsna var femte sekund genom att använda setInterval.

Slutligen måste vi skapa HTTP-servern för att hantera förfrågningar.

 http.createServer (funktion (begäran, svar) var uri = url.parse (request.url) .pathname; if (uri === "/ stream") var lyssnare = tweet_emitter.addListener ("tweets" tweets) response.sendHeader (200, "Content-Type": "text / plain"); response.write (JSON.stringify (tweets)); response.close (); clearTimeout (timeout);); var timeout = setTimeout (funktion () response.sendHeader (200, "Content-Type": "text / plain"); response.write (JSON.stringify ([])); response.close (); tweet_emitter .removeListener (lyssnare);, 10000); annars load_static_file (uri, svar);). lyssna (8080); sys.puts ("Server körs på http: // localhost: 8080 /");

Precis som vi gjorde med vår statiska filserver skapar vi en HTTP-server som lyssnar på port 8080. Vi analyserar den begärda webbadressen och om webbadressen är lika med "/strömma", Vi hanterar det, annars skickar vi förfrågan till vår statiska filserver. Streaming består av att skapa en lyssnare för att lyssna på nya tweets på vår tweet_emitter, som kommer att utlösas av vår get_tweets fungera. Vi skapar också en timer för att döda förfrågningar tht senast 10 sekunder genom att skicka dem en tom array. När nya tweets kommer in skickar vi tweetsna som JSON-data och rensar timern. Du kommer att se hur det fungerar bättre efter att ha sett kundens sidokod, vilket är under. Spara det som test.html i samma katalog som serverns JavaScript.

    Tweet Streamer    

    Här har vi en enkel HTML-sida som importerar jQuery-biblioteket och definierar en oorderad lista för att lägga in tweetsna. Vår klientsida JavaScript cacher tweetlistan och kör den load_tweets funktion efter en sekund. Detta ger webbläsaren tillräckligt med tid för att slutföra läsningen av sidan innan vi startar AJAX-förfrågan till servern. De load_tweets funktionen är mycket enkel: den använder jQuery s getJSON funktion att ladda /strömma. När ett svar kommer in går vi igenom alla tweets och lägger dem på tweetlistan. Då ringer vi load_tweets igen. Detta skapar effektivt en slinga som laddar nya tweets, som tider ut efter tio sekunder på grund av timeout på servern. När det finns nya tweets, drivs de till klienten som upprätthåller en kontinuerlig anslutning till servern. Denna teknik kallas lång polling.

    Om du kör servern med nod och gå till http: // localhost: 8080 / test.html, Du kommer att se Twitter-tidslinjen för offentlig tid i din webbläsare.


    Nästa steg

    Node.js är en mycket spännande teknik som gör det enkelt att skapa högpresterande realtidsprogram. Jag hoppas att du kan se dess fördel, och kan använda den i några av dina egna applikationer. På grund av Nodes stora modulsystem är det enkelt att använda förskriven kod i din applikation, och det finns många tredjepartsmoduler tillgängliga för nästan allting - inklusive databasförbindelseskikt, templerande motorer, postklienter och till och med hela ramar som förbinder alla dessa saker tillsammans. Du kan se en komplett lista över moduler på Node.js wiki, och mer Node-tutorials finns på hur man gör nod. Jag rekommenderar också att du tittar på en video från JSConf, där Ryan Dahl, skaparen av Node, beskriver designfilosofin bakom Node. Det är tillgängligt .

    Jag hoppas att du har haft denna handledning. Om du har några kommentarer, kan du lämna en här eller skicka ett meddelande till mig på Twitter. Glad nicka!