2016-04-08 14 views
19

Ultimamente ho svolto molte ricerche nel nucleo di Node.js e ho alcune domande sul funzionamento interno della piattaforma Node. Da quanto ho capito, Node.js funziona così:Come viene interpretato ed eseguito javascript asincrono in Node.js?

enter image description here

nodo ha un API, scritto in JavaScript, che permette al programmatore di interagire con le cose come il file system e la rete. Tuttavia, tutte queste funzionalità sono effettivamente eseguite dal codice C/C++, anch'esso parte del Nodo. Qui è dove le cose diventano un po 'confuse. Quindi il lavoro del motore V8 di Chrome è essenzialmente "compilare" (interpretare?) Javascript in codice macchina. V8 è scritto in C++ e il linguaggio Javascript stesso è specificato da ECMA, quindi elementi come parole chiave e caratteristiche della lingua sono definiti da loro. Questo mi porta a mie prime domande:

  1. Come è la libreria standard nodo in grado di interagire con le Associazioni dei nodi, dal momento che le Associazioni dei nodi sono scritte in C++?

  2. In che modo il motore V8 di Chrome interpreta Javascript nel contesto del nodo? So che utilizza una tecnica chiamata JIT, che è stata menzionata in una domanda simile: (https://softwareengineering.stackexchange.com/questions/291230/how-does-chrome-v8-work-and-why-was-javascript-not-jit-compiled-in-the-first-pl) Ma questo non spiega come viene interpretato Javascript nel contesto del nodo. Il motore V8 di Chrome fornito con Node è esattamente lo stesso motore che gira sul browser Chrome o è stato modificato per funzionare con il nodo?

Questo mi porta alla mia prossima domanda. So Node include un IO non bloccato e basato sugli eventi. Ciò avviene tramite l'Event Loop, che, sebbene venga spesso definito come il "Node Event Loop", è in realtà una parte della libreria libuv, una libreria C++ progettata per fornire un IO asincrono. Ad un livello elevato, il loop degli eventi è essenzialmente accessibile tramite Callbacks, che è una funzionalità Javascript nativa e uno dei motivi per cui Javascript è stato scelto come lingua per il progetto Node. Di seguito è un esempio del come funziona il ciclo degli eventi:

enter image description here

Questo può anche essere dimostrato dal vivo da questo piccolo sito pulito: http://latentflip.com/loupe/ Diciamo che la nostra applicazione nodo ha bisogno di fare una chiamata a un API esterna. Quindi scriviamo questo:

request(..., function eyeOfTheTiger() { 
    console.log("Rising up to the challenge of our rival"); 
}); 

La nostra chiamata alla request viene inserito nello stack delle chiamate, e la nostra callback sono passati da qualche parte, dove è conservato fino a quando l'operazione di richiesta termina. Quando lo fa, il callback viene passato alla coda di callback. Ogni volta che lo stack di chiamate viene cancellato, il ciclo di eventi spinge l'elemento nella parte superiore della coda di callback sullo stack di chiamate, dove viene eseguito. Questo ciclo di eventi viene eseguito su un singolo thread. In caso di problemi si verifica quando qualcuno scrive codice "bloccante" o codice che non lascia mai lo stack delle chiamate e attacca efficacemente il thread. Se c'è sempre un codice in esecuzione nello stack delle chiamate, il ciclo degli eventi non sposterà mai gli elementi dalla coda di callback sullo stack delle chiamate e non verranno mai eseguiti, in pratica bloccando l'applicazione. Questo mi porta alla mia prossima domanda:

  1. Se il Javascript viene interpretato dal motore di Chrome V8, che cosa "controlla" la spinta del codice sulla coda di callback? In che modo il codice Javascript è gestito dal ciclo degli eventi di libuv?

ho trovato questa immagine come una dimostrazione del processo:

enter image description here

Questo è dove sono incerti su come esattamente cromo motore V8 e libuv interagire. Sono propenso a credere che i Node Bindings facilitano questa interazione, ma non sono abbastanza sicuro di come. Nell'immagine sopra, sembra che i binding NodeJS stiano interagendo solo con il codice macchina che è stato compilato da Javascript by V8. Se è così, allora sono confuso su come il motore V8 interpreti il ​​Javascript in modo tale che i Binding del nodo possano distinguere tra la callback e il codice effettivo da eseguire immediatamente.

So che questa è una serie di domande molto profonde e complicate, ma credo che ciò contribuirà a chiarire un sacco di confusione per le persone che cercano di capire Node.js, e anche aiutare i programmatori a comprendere i vantaggi e gli svantaggi di IO comandato da eventi e non bloccante a un livello più fondamentale.

Aggiornamento di stato: Ho appena guardato un discorso fantastico da una conferenza Sencha (Link here). In questo discorso, il relatore menziona la guida per l'incorporamento di V8 (Link here) e parla di come le funzioni di C++ possono essere esposte a Javascript e viceversa. Essenzialmente come funziona è che le funzioni di C++ possono essere esposte a V8 e anche specificare come vuole che questi oggetti siano esposti a Javascript, e l'interprete V8 sarà in grado di riconoscere le funzioni C++ integrate ed eseguirle se trova Javascript che corrisponde a cosa hai specificato Ad esempio, puoi esporre variabili e funzioni a V8 che sono effettivamente scritte in C++. Questo è essenzialmente ciò che fa Node.js; è in grado di aggiungere funzioni come require in Javascript che effettivamente eseguono il codice C++ quando vengono chiamate. Ciò chiarisce brevemente la domanda numero 1, ma non mostra esattamente come la libreria standard del nodo funzioni in congiunzione con V8. Non è ancora chiaro come la libuv stia interagendo con questo.

+1

Nel tentativo di rispondere alla tua domanda, credo che quello che stai cercando sia questo: https://developers.google.com/v8/embed#templates. Espone fondamentalmente tutto il codice C++ come funzioni JavaScript che è possibile chiamare dalla VM V8. È possibile definire un callback C++ usando qualcosa chiamato come callback 'accessor'. Questo viene richiamato ogni volta che una specifica proprietà di un oggetto viene raggiunta dal tuo codice. C'è un articolo molto carino che spiega tutto questo - https://medium.com/@ghaiklor/how-nodejs-works-bfe09efc80ca#.xe4euk396 – booleanhunter

+0

Risorsa eccezionale. Vuoi scrivere una risposta formale per ottenere la taglia? –

+0

Sicuro. Non ho provato a fare quello che dice la risorsa, quindi lo farò prima e poi modificherò la mia risposta per essere più dettagliata. – booleanhunter

risposta

12

Fondamentalmente quello che stai cercando è V8 Templates. Espone tutto il tuo codice C++ come funzioni JavaScript che puoi chiamare dalla V8 Virtual Machine. È possibile associare callback C++ quando le funzioni vengono richiamate o quando si accede a proprietà specifiche dell'oggetto (Leggi Accessors e Interceptors).

Ho trovato un ottimo articolo che spiega tutto questo - How does NodeJS work?. Spiega anche come la libuv funzioni in congiunzione con il nodo per ottenere l'asincronicità.

Spero che questo aiuti!

Problemi correlati