Che cos'è Node.js? [chiuso]


506

Io non pienamente ottengo quello Node.js è tutto. Forse è perché sono principalmente uno sviluppatore di applicazioni business basato sul web. Che cos'è e a che cosa serve?

La mia comprensione finora è che:

  1. Il modello di programmazione è guidato dagli eventi, in particolare il modo in cui gestisce I / O .
  2. Utilizza JavaScript e il parser è V8 .
  3. Può essere facilmente utilizzato per creare applicazioni server simultanee.

Le mie comprensioni sono corrette? In caso affermativo, quali sono i vantaggi dell'eventuale I / O, è solo qualcosa di più per la concorrenza? Inoltre, la direzione di Node.js è diventata un modello di programmazione basato su JavaScript (basato su V8)?

Risposte:


213

Penso che i vantaggi siano:

  1. Sviluppo Web in un linguaggio dinamico (JavaScript) su una VM incredibilmente veloce (V8). È molto più veloce di Ruby, Python o Perl.

  2. Capacità di gestire migliaia di connessioni simultanee con un sovraccarico minimo su un singolo processo.

  3. JavaScript è perfetto per i loop di eventi con oggetti funzione e chiusure di prima classe. Le persone sanno già come usarlo in questo modo dopo averlo utilizzato nel browser per rispondere agli eventi avviati dall'utente.

  4. Molte persone conoscono già JavaScript, anche le persone che non dichiarano di essere programmatori. È probabilmente il linguaggio di programmazione più popolare.

  5. L'uso di JavaScript su un server Web e sul browser riduce l'incongruenza di impedenza tra i due ambienti di programmazione che possono comunicare tramite JSON strutture di dati che funzionano allo stesso modo su entrambi i lati dell'equazione. Il codice di convalida del modulo duplicato può essere condiviso tra server e client, ecc.


1
@postfuturist: in realtà funziona bene contro molte alternative. Batte Java 6 abbastanza facilmente anche in molti casi. ! Neat
Adam Crossland,

1
@postfuturist Penso che tu abbia confrontato con Java 6-Xint. Prova a confrontare con java 6
-server

@iJK yammer.com è un'applicazione funzionante di node.js
Gerard Banasig,

1
Divertente, stavo scrivendo JScript in ASP 10 anni fa in modo da poter (a) evitare la terribile VBScript, (b) usare la stessa lingua sul client e sul server e (c) riutilizzare le mie librerie JS mie e di altre per la gestione delle stringhe ... ecc.
Antony Quinn,

4
@Perché hai modificato questo post solo per "Stronzate legacy"? Non credo che 212 persone avrebbero votato per questo post se lo avessi scritto dall'inizio.
Julien Fouilhé,

619

Uso Node.js al lavoro e lo trovo molto potente. Costretto a scegliere una parola per descrivere Node.js, direi "interessante" (che non è un aggettivo puramente positivo). La comunità è vibrante e in crescita. JavaScript, nonostante le sue stranezze, può essere un ottimo linguaggio per codificare. E ripenserai quotidianamente la tua comprensione delle "migliori pratiche" e dei modelli di codice ben strutturato. C'è un'enorme energia di idee che scorre in Node.js in questo momento, e lavorare in esso ti espone a tutto questo pensiero: un ottimo sollevamento pesi mentale.

Node.js in produzione è sicuramente possibile, ma lontano dalla distribuzione "chiavi in ​​mano" apparentemente promessa dalla documentazione. Con Node.js v0.6.x, "cluster" è stato integrato nella piattaforma, fornendo uno degli elementi costitutivi essenziali, ma il mio script "production.js" è ancora ~ 150 righe di logica per gestire cose come la creazione del log directory, riciclaggio dei lavoratori morti, ecc. Per un servizio di produzione "serio", devi anche essere pronto a limitare le connessioni in entrata e fare tutto ciò che Apache fa per PHP . Ad essere onesti, Ruby on Rails ha questo esatto problema. È risolto tramite due meccanismi complementari: 1) Mettere Ruby su Rails / Node.Apache / che gestirà i processi di lavoro, li riciclerà periodicamente, ecc. Devo ancora trovare un framework di servizio Node.js che sembra completamente cotto; potrebbe esistere, ma non l'ho ancora trovato e uso ancora ~ 150 righe nel mio "production.js" arrotolato a mano.Lighttd ). Il server web può servire in modo efficiente contenuto statico, accedere alla registrazione, riscrivere gli URL, terminare SSL , applicare regole di accesso e gestire più servizi secondari. Per le richieste che raggiungono il servizio nodo effettivo, il server Web inoltra la richiesta tramite. 2) Utilizzo di un framework come Unicorn

La lettura di framework come Express fa sembrare che la pratica standard sia semplicemente quella di servire tutto attraverso un servizio Node.js tuttofare ... "app.use (express.static (__ dirname + '/ public'))" . Per servizi a basso carico e sviluppo, probabilmente va bene. Ma non appena provi a caricare molto tempo il tuo servizio e lo esegui 24 ore su 24, 7 giorni su 7, scoprirai rapidamente le motivazioni che spingono i grandi siti a disporre di un codice C ben consolidato, come Nginx che fronteggia il loro sito e gestisce tutto delle richieste di contenuto statico (... fino a quando non si imposta un CDN , come Amazon CloudFront )). Per un approccio un po 'umoristico e spudoratamente negativo su questo, vedi questo ragazzo .

Node.js sta trovando anche sempre più usi non di servizio. Anche se stai usando qualcos'altro per servire il contenuto web, potresti comunque usare Node.js come strumento di compilazione, usando i moduli npm per organizzare il tuo codice, Browserify per ricucirlo in una singola risorsa e uglify-js per minimizzarlo per la distribuzione . Per quanto riguarda il Web, JavaScript è una corrispondenza di impedenza perfetta e spesso lo rende la via di attacco più semplice. Ad esempio, se si desidera passare attraverso un sacco di payload di risposta JSON , è necessario utilizzare il mio modulo CLI di sottolineatura , la cintura di utilità dei dati strutturati.

Pro e contro:

  • Pro: Per un ragazzo server, scrivere JavaScript sul back-end è stato un "farmaco gateway" per l'apprendimento dei moderni schemi di interfaccia utente. Non ho più paura di scrivere il codice client.
  • Pro: tende a incoraggiare il corretto controllo degli errori (err viene restituito praticamente da tutti i callback, assillando il programmatore per gestirlo; inoltre, async.js e altre librerie gestiscono il paradigma "fall se una di queste attività secondarie fallisce" molto meglio del tipico codice sincrono )
  • Pro: alcune attività interessanti e normalmente difficili diventano banali, come ottenere lo stato delle attività in volo, comunicare tra i lavoratori o condividere lo stato della cache
  • Pro: community enorme e tonnellate di ottime librerie basate su un solido gestore di pacchetti (npm)
  • Contro: JavaScript non ha una libreria standard. Ti abitui così tanto all'importazione di funzionalità che sembra strano quando usi JSON.parse o qualche altro metodo build in che non richiede l'aggiunta di un modulo npm. Ciò significa che ci sono cinque versioni di tutto. Anche i moduli inclusi nel "core" di Node.js hanno altre cinque varianti se non sei soddisfatto dell'implementazione predefinita. Ciò porta a una rapida evoluzione, ma anche a un certo livello di confusione.

Contro un semplice modello a processo singolo ( LAMP ):

  • Pro: scalabile fino a migliaia di connessioni attive. Molto veloce e molto efficiente. Per una flotta web, ciò potrebbe significare una riduzione di 10 volte il numero di caselle richieste rispetto a PHP o Ruby
  • Pro: scrivere modelli paralleli è facile. Immagina di dover recuperare tre (o N) BLOB da Memcached . Fallo in PHP ... hai appena scritto il codice recupera il primo BLOB, poi il secondo, poi il terzo? Wow, è lento. C'è un PECL speciale modulo per risolvere quel problema specifico per Memcached, ma cosa succede se si desidera recuperare alcuni dati Memcached in parallelo con la query del database? In Node.js, poiché il paradigma è asincrono, avere una richiesta Web che fa più cose in parallelo è molto naturale.
  • Contro: il codice asincrono è fondamentalmente più complesso del codice sincrono e la curva di apprendimento iniziale può essere difficile per gli sviluppatori senza una solida comprensione di cosa significhi effettivamente l'esecuzione simultanea. Tuttavia, è enormemente meno difficile che scrivere qualsiasi tipo di codice multithreading con il blocco.
  • Contro: se una richiesta ad alta intensità di calcolo viene eseguita, ad esempio, per 100 ms, bloccherà l'elaborazione di altre richieste che vengono gestite nello stesso processo Node.js ... AKA, cooperativa-multitasking . Ciò può essere mitigato con il modello Web Workers (scissione di un sottoprocesso per gestire l'attività costosa). In alternativa, è possibile utilizzare un gran numero di lavoratori Node.js e consentire a ciascuno di gestire una singola richiesta contemporaneamente (ancora abbastanza efficiente perché non è possibile riciclare il processo).
  • Contro: l'esecuzione di un sistema di produzione è MOLTO più complicata di un modello CGI come Apache + PHP, Perl , Ruby , ecc. Eccezioni non gestite faranno cadere l'intero processo, richiedendo la logica per riavviare i lavoratori falliti (vedi cluster ). I moduli con codice nativo difettoso possono arrestare il processo. Ogni volta che un lavoratore muore, tutte le richieste che stava gestendo vengono eliminate, quindi un'API buggy può facilmente degradare il servizio per altre API ospitate.

Contro la scrittura di un servizio "reale" in Java / C # / C (C? Davvero?)

  • Pro: eseguire operazioni asincrone in Node.js è più semplice rispetto alla sicurezza dei thread in qualsiasi altro luogo e offre probabilmente maggiori vantaggi. Node.js è il paradigma asincrono di gran lunga meno doloroso in cui abbia mai lavorato. Con buone librerie, è solo leggermente più difficile della scrittura di codice sincrono.
  • Pro: nessun bug di multithreading / blocco. È vero, investi in anticipo nello scrivere codice più dettagliato che esprima un flusso di lavoro asincrono adeguato senza operazioni di blocco. E devi scrivere alcuni test e far funzionare il tutto (è un linguaggio di scripting e i nomi delle variabili di diteggiatura grassa vengono catturati solo al momento del test unitario). MA, una volta che lo fai funzionare, la superficie per gli heisenbugs - strani problemi che si manifestano solo una volta su un milione di corse - quella superficie è solo molto più bassa. Le tasse che scrivono il codice Node.js sono pesantemente caricate in anticipo nella fase di codifica. Quindi tendi a finire con un codice stabile.
  • Pro: JavaScript è molto più leggero per esprimere la funzionalità. È difficile dimostrarlo con le parole, ma JSON , tipizzazione dinamica, notazione lambda, eredità prototipale, moduli leggeri, qualunque cosa ... tende solo a prendere meno codice per esprimere le stesse idee.
  • Contro: Forse ti piacciono davvero tanto i servizi di codifica in Java?

Per un'altra prospettiva su JavaScript e Node.js, dai un'occhiata a Da Java a Node.js , un post sul blog sulle impressioni e le esperienze di uno sviluppatore Java sull'apprendimento di Node.js.


Moduli Quando si considera il nodo, tenere presente che la scelta delle librerie JavaScript DEFINIRÀ la propria esperienza. La maggior parte delle persone usa almeno due, un aiutante di pattern asincrono (Step, Futures, Async) e un modulo di zucchero JavaScript ( Underscore.js ).

Helper / JavaScript Sugar:

  • Underscore.js : usa questo. Fallo e basta. Rende il tuo codice piacevole e leggibile con cose come _.isString () e _.isArray (). Non sono davvero sicuro di come potresti scrivere un codice sicuro altrimenti. Inoltre, per migliorare la riga di comando-fu, dai un'occhiata al mio Underscore-CLI .

Moduli asincroni:

  • Step : un modo molto elegante per esprimere combinazioni di azioni seriali e parallele. La mia raccomandazione personale. Vedi il mio post su come appare il codice Step.
  • Futures : un modo molto più flessibile (è davvero una buona cosa?) Di esprimere l'ordinamento attraverso i requisiti. Può esprimere cose come "inizia a, b, c in parallelo. Quando A e B finiscono, inizia AB. Quando A e C finiscono, inizia AC". Tale flessibilità richiede maggiore cura per evitare bug nel flusso di lavoro (come non chiamare mai il callback o chiamarlo più volte). Vedi il post di Raynos sull'uso dei futures (questo è il post che mi ha fatto "ottenere" futures).
  • Async : libreria più tradizionale con un metodo per ogni modello. Ho iniziato con questo prima della mia conversione religiosa al passo e alla successiva realizzazione che tutti gli schemi in Async potevano essere espressi al Passo con un unico paradigma più leggibile.
  • TameJS - Scritto da OKCupid, è un precompilatore che aggiunge un nuovo linguaggio primitivo "wait" per scrivere in modo elegante flussi di lavoro seriali e paralleli. Il modello sembra sorprendente, ma richiede una pre-compilazione. Sto ancora decidendo su questo.
  • StreamlineJS - concorrente di TameJS. Mi sto inclinando verso Tame, ma puoi decidere da solo.

O per leggere tutto sulle biblioteche asincrone, vedere questo panel-intervista con gli autori.

Web Framework:

  • Esprimi un ottimo framework Ruby on Rails-esk per l'organizzazione di siti web. Utilizza JADE come motore di template XML / HTML, il che rende la costruzione di HTML molto meno dolorosa, quasi persino elegante.
  • jQuery Sebbene tecnicamente non sia un modulo nodo, jQuery sta rapidamente diventando uno standard di fatto per l'interfaccia utente lato client. jQuery fornisce selettori simili a CSS per "interrogare" insiemi di elementi DOM su cui è possibile operare (impostare gestori, proprietà, stili, ecc.). Allo stesso modo, il framework CSS Bootstrap di Twitter , Backbone.js per un modello MVC e Browserify.js per ricamare tutti i tuoi file JavaScript in un singolo file. Tutti questi moduli stanno diventando standard di fatto, quindi dovresti almeno controllarli se non ne hai sentito parlare.

test:

  • JSHint - Deve usare; All'inizio non l'ho usato, il che ora sembra incomprensibile. JSLint aggiunge una serie di verifiche di base ottenute con un linguaggio compilato come Java. Parentesi non corrispondente, variabili non dichiarate, tipi di molte forme e dimensioni. Puoi anche attivare varie forme di ciò che chiamo "modalità anale" in cui verifichi lo stile degli spazi bianchi e quant'altro, il che è OK se questa è la tua tazza di tè - ma il valore reale deriva dal ricevere un feedback immediato sul numero esatto di riga in cui hai dimenticato un ")" di chiusura ... senza dover eseguire il codice e toccare la linea offensiva. "JSHint" è una variante più configurabile di Douglas Crockford s' JSLint .
  • Concorrente moka ai voti che sto iniziando a preferire. Entrambi i framework gestiscono le basi abbastanza bene, ma i modelli complessi tendono ad essere più facili da esprimere in Mocha.
  • Vows Vows è davvero piuttosto elegante. E stampa un delizioso rapporto (--spec) che mostra quali casi di test sono passati / falliti. Dedica 30 minuti all'apprendimento e puoi creare test di base per i tuoi moduli con il minimo sforzo.
  • Zombie - Test senza testa per HTML e JavaScript utilizzando JSDom come "browser" virtuale. Roba molto potente. Combinalo con Replay per ottenere test deterministici velocissimi del codice nel browser.
  • Un commento su come "pensare" test:
    • Il test non è facoltativo. Con un linguaggio dinamico come JavaScript, ci sono molto pochi controlli statici. Ad esempio, passare due parametri a un metodo che prevede 4 non si interromperà fino all'esecuzione del codice. Barra piuttosto bassa per la creazione di bug in JavaScript. I test di base sono essenziali per colmare il divario di verifica con le lingue compilate.
    • Dimentica la convalida, esegui il codice. Per ogni metodo, il mio primo caso di validazione è "niente si rompe", ed è il caso che si attiva più spesso. Dimostrando che il tuo codice viene eseguito senza generare l'80% dei bug e farà così tanto per migliorare la sicurezza del tuo codice che ti ritroverai indietro e aggiungendo i casi di validazione sfumati che hai saltato.
    • Inizia in piccolo e rompi la barriera inerziale. Siamo tutti pigri e premuti per il tempo, ed è facile vedere i test come "lavoro extra". Quindi inizia in piccolo. Scrivi test case 0 - carica il tuo modulo e segnala il successo. Se ti costringi a fare così tanto, allora la barriera inerziale ai test si rompe. Sono <30 minuti per farlo la prima volta, inclusa la lettura della documentazione. Ora scrivi il test case 1 - chiama uno dei tuoi metodi e verifica "non si rompe nulla", cioè che non ricevi un errore. Il caso di test 1 dovrebbe richiedere meno di un minuto. Con l'inerzia scomparsa, diventa facile espandere in modo incrementale la copertura del test.
    • Ora evolvi i tuoi test con il tuo codice. Non lasciarti intimidire da come sarebbe il test end-to-end "corretto" con server simulati e tutto il resto. Il codice inizia in modo semplice e si evolve per gestire nuovi casi; anche i test dovrebbero. Man mano che aggiungi nuovi casi e nuova complessità al tuo codice, aggiungi casi di test per esercitare il nuovo codice. Quando trovi dei bug, aggiungi verifiche e / o nuovi casi per coprire il codice difettoso. Quando esegui il debug e perdi la fiducia in un pezzo di codice, torna indietro e aggiungi dei test per dimostrare che sta facendo quello che pensi che sia. Acquisisci stringhe di dati di esempio (da altri servizi che chiami, siti Web che scarichi, qualunque cosa) e inseriscili nel tuo codice di analisi. Alcuni casi qui, una migliore convalida lì e ti ritroverai con un codice altamente affidabile.

Inoltre, controlla l' elenco ufficiale dei moduli Node.js consigliati. Tuttavia, il Wiki dei moduli di nodo di GitHub è molto più completo e una buona risorsa.


Per comprendere il nodo, è utile considerare alcune delle scelte chiave di progettazione:

Node.js è EVENT BASED e ASYNCHRONOUS / NON-BLOCKING. Eventi, come una connessione HTTP in entrata, attiveranno una funzione JavaScript che svolge un po 'di lavoro e dà il via ad altre attività asincrone come la connessione a un database o l'estrazione di contenuti da un altro server. Una volta avviate queste attività, la funzione evento termina e Node.js ritorna in modalità sospensione. Non appena succede qualcos'altro, come la connessione al database stabilita o il server esterno che risponde con il contenuto, le funzioni di callback vengono attivate e viene eseguito più codice JavaScript, potenzialmente dando il via a attività ancora più asincrone (come una query del database). In questo modo, Node.js alternerà felicemente le attività per più flussi di lavoro paralleli, eseguendo qualunque attività sia sbloccata in qualsiasi momento. Questo è il motivo per cui Node.js fa un ottimo lavoro gestendo migliaia di connessioni simultanee.

Perché non usare solo un processo / thread per connessione come tutti gli altri?In Node.js, una nuova connessione è solo un'allocazione di heap molto piccola. L'avvio di un nuovo processo richiede molta più memoria, un megabyte su alcune piattaforme. Ma il costo reale è il sovraccarico associato al cambio di contesto. Quando hai 10 ^ 6 thread del kernel, il kernel deve fare molto lavoro per capire chi dovrebbe eseguire il prossimo. Un sacco di lavoro è stato dedicato alla costruzione di uno scheduler O (1) per Linux, ma alla fine è solo molto più efficiente avere un singolo processo guidato dagli eventi rispetto a 10 ^ 6 processi in competizione per il tempo della CPU. Inoltre, in condizioni di sovraccarico, il modello multi-processo si comporta in modo molto scarso, affamando i servizi di amministrazione e gestione critici, in particolare SSHD (il che significa che non è nemmeno possibile accedere alla scatola per capire quanto sia fottuto).

Node.js è SINGOLO FILETTATO e SENZA BLOCCO . Node.js, come scelta progettuale molto deliberata, ha un solo thread per processo. Per questo motivo, è fondamentalmente impossibile per più thread accedere ai dati contemporaneamente. Pertanto, non sono necessari blocchi. Le discussioni sono difficili. Davvero molto difficile. Se non ci credi, non hai fatto abbastanza programmazione thread. Ottenere il blocco corretto è difficile e risulta in bug che sono davvero difficili da rintracciare. L'eliminazione di blocchi e multi-thread fa scomparire una delle classi più cattive di bug. Questo potrebbe essere il più grande vantaggio singolo del nodo.

Ma come posso sfruttare la mia scatola a 16 core?

Due strade:

  1. Per attività di calcolo pesanti come la codifica delle immagini, Node.js può attivare processi figlio o inviare messaggi a processi di lavoro aggiuntivi. In questo progetto, avresti un thread che gestisce il flusso di eventi e N processi che svolgono compiti di calcolo pesanti e masticano le altre 15 CPU.
  2. Per ridimensionare il throughput su un servizio Web, è necessario eseguire più server Node.js su una casella, una per core, utilizzando il cluster (Con Node.js v0.6.x, il modulo "cluster" ufficiale collegato qui sostituisce la versione di learnboost che ha un'API diversa). Questi server Node.js locali possono quindi competere su un socket per accettare nuove connessioni, bilanciando il carico su di essi. Una volta accettata una connessione, questa diventa strettamente legata a uno di questi processi condivisi. In teoria, suona male, ma in pratica funziona abbastanza bene e ti permette di evitare il mal di testa di scrivere un codice thread-safe. Inoltre, ciò significa che Node.js ottiene un'eccellente affinità con la cache della CPU, utilizzando in modo più efficace la larghezza di banda della memoria.

Node.js ti consente di fare alcune cose davvero potenti senza sudare. Supponiamo di avere un programma Node.js che esegue una varietà di attività, ascolta su unaporta TCP per i comandi, codifica alcune immagini, qualunque cosa. Con cinque righe di codice, è possibile aggiungere un portale di gestione Web basato su HTTP che mostra lo stato corrente delle attività attive. È facile da fare:

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");

Ora puoi premere un URL e controllare lo stato del processo in esecuzione. Aggiungi alcuni pulsanti e hai un "portale di gestione". Se hai uno script Perl / Python / Ruby in esecuzione, semplicemente "lanciare un portale di gestione" non è esattamente semplice.

Ma JavaScript non è lento / cattivo / cattivo / spawn-of-the-diavolo? JavaScript ha alcune strane stranezze, ma con "le parti buone" c'è un linguaggio molto potente lì, e in ogni caso, JavaScript è la lingua sul client (browser). JavaScript è qui per rimanere; altre lingue lo prendono come un IL e talenti di livello mondiale sono in competizione per produrre i motori JavaScript più avanzati. A causa del ruolo di JavaScript nel browser, un'enorme quantità di sforzi ingegneristici è stata lanciata nel rendere JavaScript estremamente rapido. V8è l'ultimo e il più grande motore javascript, almeno per questo mese. Spazza via gli altri linguaggi di scripting sia in efficienza che in stabilità (guardandoti, Ruby). E migliorerà solo con enormi team che lavorano sul problema in Microsoft, Google e Mozilla, in competizione per costruire il miglior motore JavaScript (Non è più un "interprete" JavaScript poiché tutti i motori moderni fanno tonnellate di JITcompilazione sotto il cofano con interpretazione solo come fallback per il codice di esecuzione una volta). Sì, tutti vorremmo poter correggere alcune delle più strane scelte di lingua JavaScript, ma non è poi così male. E il linguaggio è così dannatamente flessibile che non stai davvero codificando JavaScript, stai codificando Step o jQuery - più di qualsiasi altra lingua, in JavaScript, le librerie definiscono l'esperienza. Per creare applicazioni Web, devi comunque conoscere JavaScript, quindi codificare con esso sul server ha una sorta di sinergia di competenze. Non mi ha fatto paura di scrivere il codice client.

Inoltre, se odi davvero JavaScript, puoi usare lo zucchero sintattico come CoffeeScript . O qualsiasi altra cosa che crei codice JavaScript, come Google Web Toolkit (GWT).

A proposito di JavaScript, cos'è una "chiusura"? - Praticamente un modo fantasioso per dire che si mantengono variabili con ambito lessicale nelle catene di chiamate. ;) Come questo:

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();

Vedi come puoi semplicemente usare "myData" senza fare nulla di imbarazzante come metterlo in un oggetto? E a differenza di Java, la variabile "myData" non deve essere di sola lettura. Questa potente funzionalità linguistica rende la programmazione asincrona molto meno dettagliata e meno dolorosa.

Scrivere codice asincrono sarà sempre più complesso della scrittura di un semplice script a thread singolo, ma con Node.js non è molto più difficile e ottieni molti vantaggi oltre all'efficienza e alla scalabilità di migliaia di connessioni simultanee. ..


"la variabile 'myData' non deve essere di sola lettura" - sembra che tu voglia mantenerla immutabile il più delle volte per prevenire problemi di concorrenza, giusto?
Nick,

1
@Nick - questo è falso. i "problemi di concorrenza" sono mitigati dal fatto che il nodo è a thread singolo. Il blocco nel nodo semplicemente non esiste; non è necessario in un paradigma a thread singolo.
Dave Dopson,


1
ps, nota a margine: in realtà l'ho modificato abbastanza volte che il post è diventato "wiki della community" (la soglia è di 10 modifiche). Ho erroneamente pensato che fosse una sorta di onore, quando in realtà blocca solo il guadagno di reputazione dai voti positivi. Alla fine, uno degli elettori pre-CW ha fatto clic su "non votato" (si spera, per caso :) e ho perso la reputazione ... confuso Ho archiviato meta.stackexchange.com/questions/129941/… ed è stato istruito in quale "Community Wiki "in realtà significa. Le mod sono state così gentili da rimuovere lo stato CW. :)
Dave Dopson,

1
@John - il mio commento di debug si applica assolutamente anche alla vanilla asnyc. Per interrompere il debug, tutto ciò che devo fare è avvolgere alcune chiamate di funzione in "process.nextTick (...)". Quindi, quando viene lanciato, la mia traccia dello stack inizierà con process.nextTick; non così utile. Quello che voglio veramente sapere è: "quale stack ha programmato process.nextTick?" Io chiamo i dati "catene causali" e mi ricorda "CauseBy" nella gestione delle eccezioni Java ... Lancio di codice di basso livello, codice di livello medio intercetta l'eccezione LL e genera FrameworkMethodFailedException - senza "CauseBy", lo stack dall'LL il codice andrebbe perso.
Dave Dopson,

85

V8 è un'implementazione di JavaScript. Ti consente di eseguire applicazioni JavaScript indipendenti (tra le altre cose).

Node.js è semplicemente una libreria scritta per V8 che presenta eventi di I / O. Questo concetto è un po 'più complicato da spiegare, e sono sicuro che qualcuno risponderà con una spiegazione migliore di me ... L'essenza è che invece di fare un input o un output e aspettare che accada, non aspetti affinché finisca. Quindi, ad esempio, chiedi l'ora dell'ultima modifica di un file:

// Pseudo code
stat( 'somefile' )

Ciò potrebbe richiedere un paio di millisecondi o potrebbe richiedere alcuni secondi. Con gli I / O eventati semplicemente si disattiva la richiesta e invece di attendere intorno si allega un callback che viene eseguito al termine della richiesta:

// Pseudo code
stat( 'somefile', function( result ) {
  // Use the result here
} );
// ...more code here

Questo lo rende molto simile al codice JavaScript nel browser (ad esempio, con funzionalità stile Ajax ).

Per ulteriori informazioni, dovresti dare un'occhiata all'articolo Node.js che è davvero entusiasmante, che è stata la mia introduzione alla libreria / piattaforma ... L'ho trovato abbastanza buono.


4
In che modo viene implementato l'IO evented senza utilizzare i blocchi, utilizzando thread, processo, chiusure? E ho la sensazione che i concetti siano abbastanza simili a quelli della programmazione funzionale e di Erlang.
Jeff,

1
Per quanto ne so, è implementato come un semplice ciclo di eventi. v8 ha già la funzionalità di callback / etc, proprio come qualsiasi implementazione javascript.
rfunduk,

2
Il ciclo di eventi IO di node.js significa che in un dato momento al massimo viene eseguita solo una cosa. Vedo due vantaggi significativi: non vi è alcun sovraccarico di cambio di thread, quindi node.js è molto veloce, e in secondo luogo molti tipici bug di concorrenza per i quali Java è noto non sono possibili.
nalply

1
"Come viene implementato l'Io evented senza usare ... chiusure?" JavaScript supporta le chiusure e vengono utilizzate continuamente in node.js (funzioni anonime e nell'esempio qui).
Panzi,

@panzi: non ho notato che Jeffrey ha incluso chiusure nella sua lista di cose node.js è implementato 'senza'. Ovviamente ogni funzione in JavaScript è una chiusura attorno al suo ambito :)
rfunduk

35

Node.js è uno strumento da riga di comando open source creato per il codice JavaScript lato server. Puoi scaricare un tarball , compilare e installare il sorgente. Ti permette di eseguire programmi JavaScript.

JavaScript viene eseguito dal V8 , un motore JavaScript sviluppato da Google che viene utilizzato nel browser Chrome . Utilizza un'API JavaScript per accedere alla rete e al file system.

È famoso per le sue prestazioni e la capacità di eseguire operazioni parallele.

Comprendere node.js è la migliore spiegazione di node.js che ho trovato finora.

Di seguito sono riportati alcuni buoni articoli sull'argomento.


13

Le chiusure sono un modo per eseguire il codice nel contesto in cui è stato creato.

Ciò che ciò significa per coerenza è che è possibile definire le variabili, quindi avviare un I / O senza blocco funzione e inviarle una funzione anonima per il suo callback.

Al termine dell'attività, la funzione di callback verrà eseguita nel contesto con le variabili, questa è la chiusura.

Il motivo per cui le chiusure sono così buone per scrivere applicazioni con I / O senza blocco è che è molto facile gestire il contesto delle funzioni che eseguono in modo asincrono.


8

Due buoni esempi riguardano il modo in cui gestisci i modelli e utilizzi i miglioramenti progressivi. Hai solo bisogno di alcuni pezzi leggeri di codice JavaScript per farlo funzionare perfettamente.

Consiglio vivamente di guardare e leggere questi articoli:

Scegli qualsiasi lingua e prova a ricordare come gestiresti i tuoi modelli di file HTML e cosa dovevi fare per aggiornare un singolo nome di classe CSS nella tua struttura DOM (ad esempio, un utente ha fatto clic su una voce di menu e desideri che sia contrassegnato come "selezionato" e aggiorna il contenuto della pagina).

Con Node.js è semplice come farlo nel codice JavaScript lato client. Ottieni il tuo nodo DOM e applica la tua classe CSS a quello. Ottieni il tuo nodo DOM e innerHTML i tuoi contenuti (per fare questo avrai bisogno di un codice JavaScript aggiuntivo. Leggi l'articolo per saperne di più).

Un altro buon esempio è che puoi rendere la tua pagina web compatibile sia con JavaScript attivato o disattivato con lo stesso codice. Immagina di avere una selezione della data fatta in JavaScript che consentirebbe agli utenti di raccogliere qualsiasi data utilizzando un calendario. Puoi scrivere (o utilizzare) lo stesso codice JavaScript per farlo funzionare con JavaScript attivato o disattivato.


7

Esiste un'eccellente analogia tra i fast food che spiega meglio il modello di Node.js basato sugli eventi, vedere l'articolo completo, Node.js, gli uffici del medico e i ristoranti di fast food - Comprendere la programmazione basata su eventi

Ecco un riassunto:

Se il fast food seguisse un modello tradizionale basato su thread, ordineresti il ​​tuo cibo e aspetteresti in fila fino a quando lo riceverai. La persona dietro di te non sarebbe in grado di ordinare fino a quando il tuo ordine è stato fatto. In un modello guidato da eventi, ordini il tuo cibo e poi esci dalla fila per aspettare. Tutti gli altri sono quindi liberi di ordinare.

Node.js è basato sugli eventi, ma la maggior parte dei server Web sono basati su thread. York spiega come funziona Node.js:

  • Si utilizza il browser Web per effettuare una richiesta per "/about.html" su un server Web Node.js.

  • Il server Node.js accetta la tua richiesta e chiama una funzione per recuperare quel file dal disco.

  • Mentre il server Node.js è in attesa del recupero del file, serve la successiva richiesta Web.

  • Quando il file viene recuperato, esiste una funzione di callback che viene inserita nella coda dei server Node.js.

  • Il server Node.js esegue quella funzione che in questo caso renderebbe la pagina "/about.html" e la rinvierebbe al tuo browser. "


6

Bene, lo capisco

  • L'obiettivo di Node è fornire un modo semplice per creare programmi di rete scalabili.
  • Il nodo è simile nel design e influenzato da sistemi come Ruby's Event Machine o Python's Twisted.
  • I / O evented per V8 javascript.

Per me questo significa che hai ragione in tutte e tre le ipotesi. La biblioteca sembra sicuramente promettente!


1
Molte volte trovo che la pagina sia piuttosto vaga.
Jeff,

6

Inoltre, non dimenticare di menzionare che il V8 di Google è MOLTO veloce. Converte effettivamente il codice JavaScript in codice macchina con le prestazioni corrispondenti del binario compilato. Quindi, insieme a tutte le altre grandi cose, è incredibilmente veloce.


3

D: Il modello di programmazione è event driven, in particolare il modo in cui gestisce I / O .

Corretta. Utilizza i callback, quindi qualsiasi richiesta di accesso al file system provocherebbe l'invio di una richiesta al file system e quindi Node.js inizierà l'elaborazione della sua richiesta successiva. Si preoccuperebbe solo della richiesta I / O una volta ottenuta una risposta dal file system, a quel punto eseguirà il codice di richiamata. Tuttavia, è possibile effettuare richieste I / O sincrone (ovvero bloccare le richieste). Spetta allo sviluppatore scegliere tra asincrono (richiamate) o sincrono (in attesa).

D: Utilizza JavaScript e il parser è V8.

D: Può essere facilmente utilizzato per creare applicazioni server simultanee.

Sì, anche se dovresti scrivere a mano un bel po 'di JavaScript. Potrebbe essere meglio guardare un framework, come http://www.easynodejs.com/ , che viene fornito con la documentazione online completa e un'applicazione di esempio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.