Una discussione sui moduli nodo è incompleta
senza parlare di callback e gestione degli errori.
Cosa sono i callback e perché sono essenziali per
supportare il calcolo asincrono che è molto
utile quando scriviamo applicazioni Node.js?
Come viene eseguita la gestione degli errori nelle applicazioni Node?
Parliamo brevemente di questi in questa lezione.
Prima di procedere a parlare di moduli nodo e callback,
abbiamo bisogno di capire due caratteristiche salienti circa il linguaggio JavaScript stesso.
Innanzitutto, JavaScript supporta ciò che viene chiamato come funzioni di prima classe.
Cosa intendiamo per funzioni di prima classe?
È che una funzione può essere trattata proprio come qualsiasi altra variabile.
E quindi, le funzioni possono essere passate come
parametri all'interno delle chiamate di funzione ad altre funzioni.
E questo essenzialmente ci permette di inviare funzioni come funzioni di callback che possono essere
chiamate da un altro modulo Node per ottenere un po 'di lavoro compiuto.
Quindi guarda come questo è molto utile nel supportare i callback in Node.js.
Il secondo aspetto su JavaScript è il supporto per le chiusure.
Cosa intendiamo per Chiusure?
Soprattutto, se hai familiarità con i linguaggi di programmazione funzionali,
capisci come funziona la chiusura.
Una funzione definita all'interno di un'altra funzione
ottiene automaticamente l'accesso alle variabili dichiarate nella funzione esterna.
Quindi, anche se la funzione esterna è completata,
quando la funzione interna viene eseguita in seguito, la funzione interna avrà ancora accesso ai
valori delle variabili all'interno di quella funzione esterna.
E questo è di nuovo,
utilizzato in modo molto efficace quando usiamo i callback nelle applicazioni Node.
Se sei abituato al modo standard di scrivere applicazioni,
allora hai familiarità con il calcolo sincrono in cui
specifichi un calcolo come un insieme di passaggi da eseguire uno dopo l'altro.
Ora, se si organizza il calcolo come segue,
come mostrato sul lato sinistro della diapositiva qui,
abbiamo il calcolo uno poi seguito da un calcolo lungo in esecuzione,
seguito dal calcolo due, e il calcolo tre.
Quindi, in questa disposizione,
supponiamo che
il calcolo due dipenda dal calcolo a lungo termine che completa il suo lavoro,
quindi ha senso che il calcolo due attenda fino
al completamento del calcolo a lungo termine prima che venga eseguito.
Ora, potremmo avere un altro pezzo di lavoro
da fare che è definito dal calcolo tre. Il
calcolo tre può non dipendere in alcun modo dal calcolo due,
o il calcolo a lungo termine da completare prima che venga eseguito.
Quindi, in questo caso,
se eseguiamo l'esecuzione sincrona di questo
calcolo, il calcolo tre rimarrà bloccato,
anche se non dipende dal completamento del calcolo due
o dal calcolo a lungo termine.
Quindi, la quantità di lavoro da fare con il calcolo tre,
sarà ritardata a causa della sua ragione, giusto?
Invece è ritardato a causa di qualcosa che lo precede nella sequenza di calcolo.
Ora, calcolo asincrono, possiamo riorganizzare questo lavoro
in modo tale che il calcolo uno, una volta completato,
possa generare quei calcoli lunghi da eseguire dietro le quinte in modo indipendente,
e poiché il calcolo due dipende dal calcolo a lungo termine per finire,
quindi il calcolo due può essere eseguito al termine del calcolo a esecuzione prolungata.
Ora, questo libera il calcolo tre per continuare,
subito dopo il calcolo uno termina.
Quindi questo modo di organizzare,
assicura che il calcolo tre finisca molto più velocemente di
essere bloccato dietro il calcolo a lungo termine e il calcolo due.
Quindi questo approccio di riorganizzare il tuo lavoro è molto utile specialmente,
quando hai un calcolo a lungo termine in particolare, il
calcolo legato all'I/O da fare.
Quindi, in questo caso, è possibile generare il calcolo associato all'I/O,
e quando ciò viene completato,
allora qualsiasi cosa debba essere eseguita in seguito,
può essere inviata ad esso come callback.
Quindi il calcolo due verrà trasformato in
un callback e quindi distribuito al calcolo a lungo termine.
Quindi, quando questo completa il suo lavoro,
richiamerà la funzione che è racchiusa all'interno del callback.
Quindi questo è sfruttato in modo molto efficace da Node.js
nel riorganizzare il calcolo all'interno delle nostre applicazioni Node.
Ora, questo è molto,
molto utile quando guardiamo il modo in cui Node.js viene eseguito.
Quindi, come ci rendiamo conto,
Node.js è organizzato in un singolo ciclo di eventi thread.
Questo ciclo di eventi a thread singolo fondamentalmente,
raccoglie le richieste man mano che entrano ed eseguono una dopo l'altra.
Ogni volta che ha bisogno di generare fuori una richiesta di
I/O, la richiesta di I/O verrà generato fuori,
e qualsiasi lavoro che deve essere fatto dopo che la richiesta di I/O è completata,
sarà racchiuso all'interno di un callback.
Quindi, quando la richiesta I/O viene completata,
inserirà il callback nella coda delle richieste
e il callback verrà gestito successivamente,
dal ciclo degli eventi.
Quindi il ciclo degli eventi è un ciclo in esecuzione continua
che raccoglie fondamentalmente le richieste dalla coda delle richieste
e quindi le gestisce una alla volta.
Quindi, quando ci ripensi,
ti rendi conto che Node.js è un singolo thread,
ma allo stesso tempo,
è in grado di ottenere un tasso molto più veloce di completamento del lavoro,
semplicemente a causa dell'uso giudizioso dei callback
e dell'esecuzione asincrona di richieste I/O,
come per file accessi o database,
o elaborazione a esecuzione prolungata che può essere eseguita indipendentemente dietro le quinte.
Ora, il modo in cui il ciclo di eventi Node.js gestisce tutto questo,
è che il ciclo di eventi è organizzato in una sequenza di fasi.
Quindi, come si vede nel diagramma mostrato qui,
le fasi includono la gestione del timer, la gestione del
callback I/O, quindi si dispone di inattività, preparare,
quindi il sondaggio in cui vengono gestite le richieste in arrivo per le connessioni o i dati,
e quindi la fase di controllo,
e infine, la fase di callback di chiusura.
Ora, alcuni dettagli su ciò che viene fatto in ciascuna di queste fasi sono elencati sul lato destro.
Nella fase di timer,
il ciclo di eventi gestisce tutto ciò che viene attivato dalla
funzione setTimeout () in JavaScript.
I callback I/O vengono eseguiti,
quasi tutti i callback che ritornano per essere
eseguiti dopo una richiesta I/O saranno gestiti dalla coda di callback I/O.
Quindi ognuna di queste fasi mantiene la propria coda separata
e il ciclo di eventi Node.js raccoglie le richieste da ciascuna di queste code e le gestisce.
Il, inattivo, preparare, è pensato per l'uso interno da parte di Node.js.
Il sondaggio è dove recupera nuovi eventi I/O da gestire e, forse,
le richieste provenienti dall'esterno.
La fase di callback di chiusura gestisce tutte le chiusure di socket che devono essere gestite e così via.
Ora, non abbiamo bisogno di preoccuparci troppo di
tutti questi dettagli se abbiamo bisogno di scrivere davvero un'applicazione Node.js.
Quando richiesto, esamineremo alcuni di questi dettagli come e quando
è essenziale per capire come funziona la nostra applicazione Node.
Ma per il momento, questo ti dà una visione
d'insieme di come viene gestito il ciclo degli eventi Node.js.
Basti dire che questa è sufficiente informazione per noi per
capire le applicazioni Node e come funzionano per il momento.
Se vuoi saperne di più,
ti ho dato un link a una descrizione dettagliata nella
documentazione Node.js che spiega il ciclo degli eventi in modo più dettagliato.
Con questa rapida comprensione del nodo,
callback, e gestione degli errori,
passeremo all'esercizio,
dove vedremo come un'applicazione nodo può scritto con callback,
e come gli errori possono essere gestiti all'interno di un'applicazione nodo.
Vedremo l'uso ripetuto di questo modello negli esercizi successivi,
e le lezioni successive in particolare,
quando guardiamo a Express,
e come costruiamo applicazioni lato server utilizzando Express
in modo più dettagliato nella parte successiva di questo corso.