Learning Server-Side JavaScript med Node.js

Node.js er alt for øyeblikket, og gjør det enkelt å lage høykvalitets web-applikasjoner i sanntid. Det tillater at JavaScript brukes til slutt, både på serveren og på klienten. Denne opplæringen vil gå deg gjennom installeringen av Node og ditt første "Hello World" -program, for å bygge en skalerbar streaming Twitter-server.

Hva er Node.js?



JavaScript har tradisjonelt bare kjørt i nettleseren, men nylig har det vært stor interesse for å bringe den til server siden også, takket være CommonJS-prosjektet. Andre server-side JavaScript-miljøer inkluderer Jaxer og Narwhal. Node.js er imidlertid litt annerledes enn disse løsningene, fordi det er hendelsesbasert i stedet for trådbasert. Webservere som Apache som brukes til å betjene PHP og andre CGI-skript, er trådbaserte fordi de henter en systemtråd for hver innkommende forespørsel. Selv om dette er bra for mange applikasjoner, går det ikke bra med den trådbaserte modellen med mange langlivede forbindelser som du trenger for å kunne bruke sanntidsprogrammer som Friendfeed eller Google Wave.

"Hver I / O-operasjon i Node.js er asynkron ..."

Node.js, bruker en hendelsesløkke i stedet for tråder, og kan skala til millioner av samtidige tilkoblinger. Det utnytter det faktum at servere bruker mesteparten av tiden på å vente på I / O-operasjoner, for eksempel å lese en fil fra en harddisk, få tilgang til en ekstern webtjeneste eller vente på at en fil skal fullføres, fordi disse operasjonene er mye langsommere enn i minnesoperasjoner. Hver I / O-operasjon i Node.js er asynkron, noe som betyr at serveren kan fortsette å behandle innkommende forespørsler mens I / O-operasjonen finner sted. JavaScript er svært godt egnet for hendelsesbasert programmering fordi den har anonyme funksjoner og nedleggelser som gjør definere inline callbacks en cinch, og JavaScript-utviklere vet allerede hvordan man programmerer på denne måten. Denne hendelsesbaserte modellen gjør Node.js veldig rask, og gjør skanning i sanntidsprogrammer veldig enkelt.


Trinn 1 Installasjon

Node.js kjører på Unix-baserte systemer, for eksempel Mac OS X, Linux og FreeBSD. Dessverre er Windows ennå ikke støttet, så hvis du er en Windows-bruker, kan du installere den på Ubuntu Linux ved hjelp av Virtualbox. For å gjøre dette, følg denne veiledningen. Du må bruke terminalen til å installere og kjøre Node.js.

  1. Last ned den nyeste versjonen av Node.js fra nodejs.org (den nyeste versjonen på tidspunktet for denne skrivingen er 0.1.31) og pakke den ut.
  2. Åpne terminalen, og kjør følgende kommandoer.
    cd / path / to / nodejs gjør sudo make install

    Mange meldinger vil bli sendt ut til terminalen som Node.js er kompilert og installert.


Trinn 2 Hei verden!

Hver ny teknologi starter med en "Hello World!" opplæring, så vi vil opprette en enkel HTTP-server som serverer denne meldingen. Først må du imidlertid forstå Node.js modulsystem. I Node er funksjonaliteten innkapslet i moduler som må lastes for å kunne brukes. Det er mange moduler som er oppført i Node.js-dokumentasjonen. Du laster disse modulene ved hjelp av krever fungere som slik:

 var sys = krever ("sys");

Dette laster sys-modulen, som inneholder funksjoner for å håndtere systemnivåoppgaver som utskriftsutgang til terminalen. For å bruke en funksjon i en modul, kaller du den på variabelen som du lagret modulen i, i vårt tilfelle sys.

 sys.puts ("Hello World!");

Kjører disse to linjene er like enkelt som å kjøre node kommandoen med filnavnet til javascriptfilen som et argument.

 node test.js

Dette vil utgjøre "Hello World!" til kommandolinjen når du kjører.

For å opprette en HTTP-server må du krever de http modul.

 var sys = krever ("sys"), http = krever ("http"); http.createServer (funksjon (forespørsel, svar) response.sendHeader (200, "Content-Type": "text / html"); response.write ("Hello World!"); response.close (); ) .listen (8080); sys.puts ("Server kjører på http: // localhost: 8080 /");

Dette skriptet importerer sys og http moduler, og oppretter en HTTP-server. Den anonyme funksjonen som overføres til http.createServer vil bli kalt når en forespørsel kommer inn på serveren. Når serveren er opprettet, blir det fortalt å lytte på port 8080. Når en forespørsel til serveren kommer inn, sender vi først HTTP-overskrifter med innholdstype og statuskode på 200 (vellykket). Så sender vi "Hello World!" og lukk forbindelsen. Det kan hende du merker at vi må eksplisitt lukke tilkoblingen. Dette gjør det veldig enkelt å streame data til klienten uten å lukke tilkoblingen. Hvis du kjører dette skriptet og går til http: // localhost: 8080 / i nettleseren din vil du se "Hello World!"


Trinn 3 En enkel statisk filserver

OK, så vi har bygget en HTTP-server, men det sender ikke noe unntatt "Hello World," uansett hvilken URL du går til. En hvilken som helst HTTP-server må kunne sende statiske filer som HTML-filer, bilder og andre filer. Følgende kode gjør akkurat det:

 var sys = krever ("sys"), http = krever ("http"), url = krever ("url"), sti = krever ("sti"), fs = krever ("fs"); http.createServer (funksjon (forespørsel, svar) var uri = url.parse (request.url) .pathname; var filnavn = path.join (process.cwd (), uri); path.exists (filnavn, funksjon ) if (! exists) response.sendHeader (404, "Content-Type": "text / plain"); response.write ("404 ikke funnet \ n"); response.close (); return;  fs.readFile (filnavn, "binært", funksjon (feil, fil) if (err) response.sendHeader (500, "Content-Type": "text / plain"); response.write "answer.write ()"; svar; response.sendHeader (200); response.write (fil, "binær"); respons.close ();););). 8080); sys.puts ("Server kjører på http: // localhost: 8080 /");

Vi starter med å kreve alle modulene vi trenger i vår kode. Dette inkluderer sys, http, url, sti, og fs eller filsystemmoduler. Deretter oppretter vi en HTTP-server som vi gjorde før. Denne gangen bruker vi url modul for å analysere den innkommende nettadressen til forespørselen og finne stiavnet til filen som skal åpnes. Vi finner det faktiske filnavnet på serverens harddisk ved å bruke path.join, som blir med process.cwd (), eller den nåværende arbeidskatalogen, med banen til filen som blir forespurt. Deretter sjekker vi om filen eksisterer, som er en asynkron operasjon og krever derfor tilbakeringing. Hvis filen ikke eksisterer, sendes en 404 Not Found-melding til brukeren, og funksjonen returnerer. Ellers leser vi filen ved hjelp av fs modul ved hjelp av "binær" koding, og send filen til brukeren. Hvis det oppstår en feil ved å lese filen, presenterer vi feilmeldingen til brukeren, og lukker tilkoblingen. Fordi alt dette er asynkront, kan serveren betjene andre forespørsler mens du leser filen fra disken, uansett hvor stor det er.

Hvis du kjører dette eksempelet, og naviger til http: // localhost: 8080 / sti / til / fil, den filen vil bli vist i nettleseren din.


Trinn 4 En Real Time Tweet Streamer

Bygger på vår statiske filserver, vil vi bygge en server i Node.js som streamer tweets til en klient som serveres via vår statiske filserver. For å starte, trenger vi en ekstra modul i dette eksemplet: arrangementer modul. Node har et konsept kalt en EventEmitter, som brukes over alt for å håndtere hendelseslyttere for asynkrone oppgaver. I likhet med jQuery eller en annen JavaScript-ramme for klientsiden der du binder hendelseslyttere til ting som museklikk og AJAX-forespørsler, kan Node binde hendelseslyttere til mange ting, noe som vi allerede har brukt. Disse inkluderer alle I / O-operasjoner, for eksempel å lese en fil, skrive en fil, kontrollere om en fil eksisterer, venter på HTTP-forespørsler, etc. EventEmitter abstrakt logikken til bindende, ubindende og utløse slike hørere. Vi skal bruke en EventEmitter å varsle lyttere når nye tweets er lastet. De første linjene i våre tweet streamer importerer alle nødvendige moduler, og definerer en funksjon for håndtering av statiske filer, som ble tatt fra vårt tidligere eksempel.

 var sys = krever ("sys"), http = krever ("http"), url = krever ("url"), sti = krever ("sti"), fs = krever ("fs"), hendelser = krever "arrangementer"); funksjon load_static_file (uri, respons) var filnavn = path.join (process.cwd (), uri); path.exists (filnavn, funksjon (eksisterer) hvis (eksisterer) response.sendHeader (404, "Content-Type": "text / plain"); response.write ("404 ikke funnet \ n") ; response.close (); return; fs.readFile (filnavn, "binært", funksjon (feil, fil) hvis (err) response.sendHeader (500, "Content-Type": "text / plain"  response.write (feil, "binær"); response.close ();) ;); 

Vi har brukt http modul for å opprette en server før, men det er også mulig å opprette en HTTP-klient ved hjelp av modulen. Vi skal opprette en HTTP-klient for å laste tweets fra Twitters offentlige tidslinje, som utføres av get_tweets funksjon.

 var twitter_client = http.createClient (80, "api.twitter.com"); var tweet_emitter = nye hendelser.EventEmitter (); funksjon get_tweets () var request = twitter_client.request ("GET", "/1/statuses/public_timeline.json", "host": "api.twitter.com"); request.addListener ("respons", funksjon (respons) var body = ""; response.addListener ("data", funksjon (data) body + = data;); response.addListener ) var tweets = JSON.parse (kropp); hvis (tweets.length> 0) tweet_emitter.emit ("tweets", tweets);;;); request.close ();  setInterval (get_tweets, 5000);

Først oppretter vi en HTTP-klient på port 80 til api.twitter.com, og oppretter en ny EventEmitter. De get_tweets funksjonen oppretter en HTTP "GET" -forespørsel til Twitters offentlige tidslinje, og legger til en hendelselytter som vil bli utløst når Twitters servere svarer. Fordi Node.js er asynkron, kommer dataene i svarets kropp i biter, som hentes av responsens "data" -lytter. Denne lytteren legger bare klumpen til kropp variabel. Når alle bitene er kommet inn, blir "slutt" -lytteren utløst, og vi analyserer de innkommende JSON-dataene. Hvis mer enn en tweet returneres, vi avgir den "tweets" hendelsen på vår tweet_emitter, og passere i rekke nye tweets. Dette vil utløse alle hendelseslytterne som lytter etter "tweets" -hendelsen, og send de nye tweets til hver klient. Vi trekker opp de nye tweets hvert femte sekund ved å bruke setInterval.

Til slutt må vi opprette HTTP-serveren for å håndtere forespørsler.

 http.createServer (funksjon (forespørsel, svar) var uri = url.parse (request.url) .pathname; if (uri === "/ stream") var lytter = tweet_emitter.addListener ("tweets" tweets) response.sendHeader (200, "Content-Type": "text / plain"); response.write (JSON.stringify (tweets)); response.close (); clearTimeout (timeout);); var timeout = setTimeout (funksjon () response.sendHeader (200, "Content-Type": "text / plain"); response.write (JSON.stringify ([])); response.close (); tweet_emitter .removeListener (lytter);, 10000); else load_static_file (uri, respons);). lytt (8080); sys.puts ("Server kjører på http: // localhost: 8080 /");

Akkurat som vi gjorde med vår statiske filserver, oppretter vi en HTTP-server som lytter på port 8080. Vi analyserer den forespurte nettadressen, og hvis nettadressen er lik "/strøm", Vi vil takle det, ellers sender vi forespørselen til vår statiske filserver. Streaming består av å lage en lytter for å lytte etter nye tweets på vår tweet_emitter, som vil bli utløst av vår get_tweets funksjon. Vi lager også en timer for å drepe forespørsler tht sist i 10 sekunder ved å sende dem en tom rekkefølge. Når nye tweets kommer inn, sender vi tweets som JSON data, og fjern timeren. Du vil se hvordan dette fungerer bedre etter å ha sett kundens sidekode, som er under. Lagre det som test.html i samme katalog som serversiden JavaScript.

    Tweet Streamer    

    Her har vi en enkel HTML-side som importerer jQuery-biblioteket og definerer en uordnet liste for å sette tweets inn. Vår klientside JavaScript caches tweetlisten, og kjører den load_tweets fungere etter et sekund. Dette gir nettleseren nok tid til å fullføre laste siden før vi starter AJAX-forespørselen til serveren. De load_tweets funksjonen er veldig enkel: Den bruker jQuery's getJSON funksjon å laste /strøm. Når et svar kommer inn, slår vi gjennom alle tweets og legger dem til tweetlisten. Da kaller vi load_tweets en gang til. Dette skaper effektivt en sløyfe som laster nye tweets, som tider ut etter ti sekunder på grunn av timeout på serveren. Når det er nye tweets, blir de presset til klienten som opprettholder en kontinuerlig tilkobling til serveren. Denne teknikken kalles langpolling.

    Hvis du kjører serveren med node og gå til http: // localhost: 8080 / test.html, Du vil se Twitter offentlig tidslinje strøm inn i nettleseren din.


    Neste skritt

    Node.js er en veldig spennende teknologi som gjør det enkelt å lage høykvalitetsprogrammer i sanntid. Jeg håper du kan se fordelene, og kan bruke den i noen av dine egne applikasjoner. På grunn av Nodes store modulsystem er det enkelt å bruke forhåndskrevet kode i søknaden din, og det finnes mange tredjepartsmoduler tilgjengelig for omtrent alt - inkludert databaseforbindelseslag, templerende motorer, postklienter og til og med hele rammer som forbinder alle disse ting sammen. Du kan se en komplett liste over moduler på Node.js wiki, og mer Node-opplæringsprogrammer finner du på Slik Knutepunkt. Jeg vil også anbefale at du ser en video fra JSConf, der Ryan Dahl, skaperen av Node, beskriver designfilosofien bak Node. Det er tilgjengelig .

    Jeg håper du har hatt denne opplæringen. Hvis du har kommentarer, kan du legge igjen en her eller sende meg en melding på Twitter. Glad nikkende!