‫Jonas: Ora scriviamo del
‫codice per avere una migliore comprensione di
‫cosa succede nel ciclo degli eventi.
‫Quindi, proprio come prima, per iniziare
‫con la parte di codifica di questa
‫sezione, vai avanti e prendi i file
‫di partenza per questa sezione, copiali da qualche
‫parte e quindi apri il progetto nel tuo editor di codice.
‫Quindi ce l'ho qui sul desktop e
‫nel mio VSCode, e tutto ciò che abbiamo qui per iniziare
‫è questo file di test. txt, quindi creerò un nuovo file qui
‫e lo chiamerò ciclo di eventi. js.
‫Bene, ora è davvero estremamente difficile simulare correttamente l'event
‫loop, perché non possiamo davvero mettere
‫molte callback in tutte le
‫code di callback
‫di cui abbiamo parlato prima tutte contemporaneamente, giusto.
‫Questa situazione si verifica quando, ad
‫esempio, arrivano molte richieste nella tua app,
‫ma qui a livello locale è molto difficile da replicare.
‫Comunque, faremo comunque degli esperimenti molto interessanti
‫usando alcune delle cose che
‫abbiamo imparato nell'ultimo video.
‫E quello che faremo è scrivere
‫un mucchio di righe di codice, e
‫poi provare a capire in quale ordine dovrebbero essere
‫eseguite nel ciclo degli eventi, e analizzare se i
‫risultati che otteniamo hanno davvero un senso.
‫Quindi iniziamo scrivendo un setTimeout, quindi
‫fondamentalmente per impostare un timer,
‫e sto usando una funzione
‫freccia qui,
‫e l'unica cosa che farò è accedere
‫a console qualche stringa, quindi console. log, timer uno terminato e
‫voglio che questo scada subito dopo zero secondi.
‫Ok, salvalo e poi vedrai che in
‫realtà ha corretto questa stringa qui, quindi
‫ha cambiato le virgolette e ha aggiunto il punto e
‫virgola, e questo è
‫dovuto all'estensione Prettier che abbiamo installato prima.
‫Ora non lo configurerò qui,
‫perché per questo
‫piccolo esempio, non è proprio necessario, ok.
‫Quindi questo è l'impostazione di un
‫timer, quindi usiamo anche setImmediate, quindi ricordalo dall'ultimo video.
‫Ok, ora non spiegherò molto qui, per
‫ora scriviamo questo codice
‫e poi analizziamo cosa succede, ok.
‫Quindi setImmediate e, proprio come l'altro timer, riceve una
‫funzione di callback.
‫E tutto quello che faremo è
‫scriverne uno finito immediato, e questo non ha tempo,
‫perché non è
‫necessario perché come dice il nome, è immediato.
‫Quindi un'altra cosa che vogliamo
‫fare è leggere questo file qui e quindi
‫passare una funzione di callback, ok, quindi la prima
‫cosa è che dobbiamo richiedere il modulo corretto, quindi FS e ora
‫fs. readFile, e vogliamo file di testo. txt,
‫e poi succede qualcosa.
‫E proprio come prima, diciamo
‫qui, in questo caso I/O finito, va bene.
‫Quindi I/O perché questo callback qui
‫è in realtà correlato a un'attività di I/O, che in
‫realtà ottiene la propria fase nel ciclo degli eventi, giusto.
‫E infine, aggiungiamo solo una console. accedi qui, dicendo
‫bene, ciao dal codice di primo livello.
‫Ok, e quindi codice di primo livello, perché in realtà
‫è l'unico che non è all'interno di alcun callback.
‫Quindi in questo piccolo esempio che abbiamo per ora,
‫proviamo a capire cosa dovrebbe accadere prima.
‫Bene, ricorda che il primo passo
‫quando carichiamo un modulo è che il suo
‫codice di primo livello viene eseguito, quindi dovremmo
‫vedere subito questa console. log qui, giusto, solo
‫in seguito dovremmo vedere gli altri log provenienti
‫da questi altri callback, perché questi
‫callback verranno effettivamente eseguiti nel ciclo degli eventi.
‫Quindi proviamo a vedere se è
‫effettivamente così, e poi analizziamolo anche un po' meglio.
‫Quindi aprendo la console qui, e di nuovo,
‫lo sto facendo usando
‫il terminale, o effettivamente nella vista, quindi questo terminale qui, va bene.
‫Quindi nota, ciclo di eventi. js, o in realtà prima
‫di farlo, devo correggere questo errore di battitura qui, quindi è un
‫file di test, non un file di testo.
‫Ok, ma ora siamo pronti per eseguire
‫questo comando e i risultati sono arrivati, quindi il primo
‫registro che abbiamo qui è ciao dal codice di livello
‫superiore, ed era previsto, giusto,
‫perché questo è un codice che viene eseguito subito.
‫Dopodiché, abbiamo questi tre output, ma in realtà non sono in
‫un ordine particolare, e questo perché questo
‫codice qui, quindi questo codice, non
‫è in realtà in un ciclo di I/O, quindi non
‫è in esecuzione all'interno del ciclo di eventi,
‫perché non è in esecuzione all'interno di alcuna funzione di callback.
‫Ok, quindi nel tuo computer, potresti effettivamente vedere questo registro
‫qui prima di questo,
‫e poi questo qui è solo
‫l'ultimo perché questo tipo di file di grandi dimensioni qui
‫richiede del tempo per essere letto, e
‫quindi probabilmente sarà sempre l'ultimo uno.
‫Quindi di nuovo, a questo punto, l'ordine di questi tre qui non ha nulla
‫a che fare con il ciclo degli eventi, perché
‫in realtà non sono ancora
‫in esecuzione all'interno del ciclo degli eventi.
‫Per questo, dovremo spostarli, o almeno
‫spostarli qui, all'interno di una funzione di callback.
‫E quindi, per questo useremo questo qui in realtà.
‫Quindi fammi mettere qui, e dire timer due e timer due
‫qui, o immediatamente due, e aggiungerò anche un altro timer qui, quindi
‫timer tre, e questo durerà
‫tre secondi, quindi sono 3000 millisecondi .
‫Quindi ora proviamo il risultato di questo.
‫Ma prima di farlo, pensiamo al
‫motivo per cui subito dopo che tutto il codice precedente era
‫stato eseguito, il programma è uscito e è tornato al prompt qui.
‫Quindi ricorda come Node. js decide se deve
‫continuare a eseguire il ciclo degli eventi, beh,
‫lo fa chiedendo se c'è ancora del tempo in
‫esecuzione in background e, in tal caso, non finirà, e
‫se c'è ancora un timer in sospeso,
‫beh, allora non lo è uscirò dal programma.
‫Ma se non c'è, come
‫nel primo esempio qui, allora esce immediatamente dal
‫programma, ok, ma ora abbiamo effettivamente un
‫timer qui, quindi questo verrà eseguito
‫per tre secondi, quindi proviamo a capire
‫cosa succede qui.
‫Ok, quindi vedi che non
‫sta uscendo, e solo ora, dopo che il timer
‫tre è terminato, è uscito dall'applicazione.
‫Ok, quindi vediamolo di nuovo, quindi tutti questi
‫timer di registro sono in esecuzione, il timer è
‫terminato e quindi è uscito dall'applicazione.
‫Ora riguardo a questi risultati qui,
‫rendiamolo un po' più facile
‫da vedere e aggiungiamo solo un piccolo separatore qui.
‫Ok, pulisci questo, ok.
‫Quindi questi quattro qui sono gli output che non
‫erano realmente in esecuzione nel ciclo degli
‫eventi, ma questi tre qui stavano
‫effettivamente uscendo dal ciclo degli eventi, quindi ora analizziamo questi risultati.
‫Ora, se ricorderai
‫il diagramma della lezione precedente, probabilmente avrai
‫pensato che il timer, quindi il timer due qui, dovrebbe effettivamente
‫finire prima del setImmediate, perché nel diagramma,
‫in realtà è apparso per primo proprio nella
‫parte superiore del ciclo di eventi.
‫Quindi dobbiamo impostare il timeout qui
‫con zero, che dovrebbe essere lo stesso di setImmediate, giusto.
‫Allora perché setImmediate
‫appare effettivamente prima di setTimeout?
‫Bene, c'è qualcosa che non ho
‫spiegato nell'ultimo video, perché non volevo rendere
‫la cosa ancora più confusa, ed è che il ciclo
‫degli eventi attende effettivamente che accadano cose nella fase di sondaggio.
‫Quindi in quella fase in cui vengono gestiti i callback di I/O.
‫Quindi, quando questa coda di callback è vuota, come
‫nel nostro esempio fittizio qui, quindi non
‫abbiamo callback I/O, tutto ciò che
‫abbiamo sono questi timer, beh, allora il ciclo degli
‫eventi aspetterà in questa fase fino a quando non è scaduto Timer.
‫Ma, se abbiamo pianificato una richiamata utilizzando setImmediate, quella
‫richiamata verrà effettivamente eseguita subito dopo la
‫fase di polling e anche
‫prima dei timer scaduti, se ce n'è uno.
‫E in questo caso, il timer scade subito, quindi
‫dopo zero secondi, ma ancora una volta, il
‫ciclo degli eventi attende effettivamente, quindi si interrompe nella fase di polling.
‫E quindi il callback setImmediate viene
‫effettivamente eseguito per primo, quindi questa è l'intera ragione
‫per cui abbiamo questo immediato qui dopo che abbiamo i timer.
‫Ok, e so che sembra molto confuso, e sono
‫completamente d'accordo, ma in realtà
‫è così che Node. js funziona.
‫E ora rendiamo questo ancora un po' più confuso e
‫aggiungiamo il processo. nextTick di
‫cui abbiamo parlato anche nell'ultima lezione.
‫Quindi diciamo processo. nextTick, e poi, proprio come prima, gli
‫passiamo semplicemente una funzione di callback.
‫E ancora, voglio solo accedere alla
‫console e dirò processo. successivoTick.
‫Quindi cosa pensi che accadrà in questo caso?
‫Vai avanti e fai un'ipotesi, e una volta che sei
‫pronto puoi eseguire questo, quindi facciamolo.
‫Prima salvalo qui, eseguilo e quindi eccoci qui.
‫Quindi i risultati sono di nuovo presenti, e ora la
‫prima richiamata che è stata eseguita era in realtà questa funzione qui.
‫Ecco perché abbiamo il processo. nextSpunta a
‫destra nel primo.
‫Allora perché questa funzione di callback del processo. nextSelezionare il
‫primo di tutti da eseguire?
‫Bene, ricorda che nextTick fa
‫parte della coda dei microtask, che vengono eseguiti
‫dopo ogni fase, quindi non solo dopo un intero tick.
‫E quindi quello che è successo qui è
‫che questa funzione di callback è stata effettivamente eseguita prima della fase in cui è stata
‫eseguita questa funzione di callback qui, e la fase precedente, ok.
‫NextTick è in realtà un nome fuorviante, perché un tick
‫è in realtà un intero ciclo, ma
‫nextTick si verifica effettivamente prima della fase del ciclo successivo,
‫e non l'intero tick, quindi è quello che stavo dicendo prima.
‫Quindi, dall'altra parte, setImmediate ti farebbe pensare che
‫il suo callback verrebbe eseguito immediatamente, ma in realtà
‫non lo fa, giusto, quindi setImmediate
‫viene effettivamente eseguito una volta
‫per tick, mentre nextTick viene eseguito immediatamente.
‫E quindi i loro due nomi dovrebbero effettivamente essere scambiati.
‫Dovrebbero essere il contrario, e questo può
‫causare molta confusione, quindi è
‫meglio attenersi sempre a uno di essi, e di solito è
‫impostato su Immediato e non su Process. successivoTick.
‫Comunque, come ho detto in un ultimo video,
‫questi meccanismi sono in realtà più per casi d'uso piuttosto
‫avanzati, motivo per cui
‫probabilmente non li useremo nel nostro progetto.
‫Ma se vuoi saperne di più su
‫di loro, puoi sempre leggere la documentazione ufficiale di Node.
‫Ok, con questo abbiamo simulato alcuni aspetti del
‫ciclo degli eventi, ma per finire, voglio
‫solo introdurre rapidamente qualcosa sul pool
‫di thread, e per questo faremo un'operazione più
‫complessa che verrà effettivamente scaricata su il pool
‫di thread e dai un'occhiata a quanto
‫tempo impiegano queste operazioni per l'esecuzione e come possiamo modificare la
‫dimensione del pool
‫di thread di cui abbiamo parlato prima.
‫Quindi useremo un po' di
‫crittografia qui per crittografare sostanzialmente una password.
‫Quindi questo è un nuovo pacchetto che
‫non avevamo mai usato prima, e si chiama Crypto, ma ho
‫detto prima che in realtà, tutte le funzioni di
‫questo pacchetto verranno scaricate automaticamente dal ciclo degli eventi nel pool
‫di thread, e quindi è quello
‫che noi proverò adesso.
‫E usiamo questo ora, quindi cripto. pb, quindi useremo una funzione
‫di crittografia chiamata pbkdf2, quindi un nome strano,
‫e ora passiamo la stringa segreta, che diciamo solo
‫password, quindi abbiamo bisogno di una stringa per risolvere
‫le password e le implementazioni qui non
‫importa, quindi per ora non entrerò nei dettagli di
‫come funziona, lo faremo più
‫tardi, ok, quindi qui abbiamo solo bisogno della
‫lunghezza della chiave, quindi questo numero
‫qui è solo
‫per numero di iterazioni, quindi questa è la lunghezza della
‫chiave e infine l'algoritmo, che
‫verrà utilizzato per crittografare la password.
‫Quindi questi numeri aumenteranno semplicemente
‫il tempo necessario per la crittografia.
‫Ok, e poi finalmente, ci vuole anche una funzione di callback, e tutto quello che farò
‫qui è fare un'altra console. log
‫e pronuncia semplicemente la password crittografata.
‫Ora, ai fini di questa
‫dimostrazione, in realtà voglio mostrarti quanto tempo
‫impiega ciascuna di queste operazioni, quindi
‫ciò che faremo è sostanzialmente definire una variabile all'inizio,
‫impostarla su data. ora, quindi questa è la data corrente
‫in millisecondi, e quindi qui, tutto ciò che dobbiamo fare è registrare non
‫solo la stringa, ma anche la data. ora, che sarà la data a
‫questo punto in millisecondi, meno l'inizio, e
‫così che ci darà la quantità di
‫millisecondi che sono passati per
‫fare questo calcolo.
‫Ok, allora proviamolo,
‫salviamolo ed eseguiamolo di nuovo, quindi qui vedete che
‫ci sono voluti 1855 millisecondi, quindi
‫quasi due secondi per crittografare questa password.
‫Ok, ma ora duplichiamo questo codice, o
‫in realtà voglio che quattro
‫istanze di questo ti mostrino qualcosa.
‫Quindi, se eseguiamo questo ora, dovrebbe probabilmente richiedere all'incirca la stessa
‫quantità di tempo, e sì, lo fa,
‫quindi era 1. 8
‫secondi, ora sono 2. 2 secondi, che è abbastanza simile.
‫Ok, e ricorda che ti ho detto in una
‫delle lezioni precedenti, che per
‫impostazione predefinita la dimensione del pool di thread
‫è quattro, quindi ci sono quattro thread
‫che fanno il lavoro contemporaneamente, ed ecco
‫perché queste quattro crittografie di password
‫richiedono circa allo stesso
‫tempo e accadono praticamente tutti allo stesso tempo.
‫Ma possiamo effettivamente modificare la dimensione del pool di thread.
‫Quindi, lascia che ti mostri come lo facciamo, e
‫lo facciamo dicendo processo. env, e
‫questa è una variabile ambientale,
‫e di nuovo ne parleremo più avanti,
‫e UV, che sta per
‫LibUV, dimensione del pool di thread, quindi se lo impostiamo su uno,
‫avremo solo un thread nel nostro pool di thread.
‫Quindi proviamo di nuovo, e vediamo cosa succede ora.
‫Quindi vedi che tutti impiegano molto più tempo per il calcolo.
‫Fondamentalmente, vengono calcolati uno dopo l'altro.
‫Quindi questo il primo, poi questo qui impiega il doppio
‫del tempo, e di nuovo questo è
‫perché questo può iniziare solo non appena il
‫primo è completato, e lo stesso con
‫il terzo e il quarto.
‫Ora diciamo di cambiarlo
‫in due, quindi dovremmo vedere i
‫primi due con lo stesso tempo, e esattamente,
‫anche i secondi due con un tempo simile.
‫Quindi ha senso, giusto.
‫Solo per completezza qui,
‫ora lo stesso con tre, quindi questi tre hanno
‫un tempo simile, e poi l'ultimo.
‫Bene, ecco come funziona fondamentalmente il pool di thread, quindi ho deciso
‫di concentrarmi non solo sul ciclo degli eventi, ma
‫anche di darti una panoramica, molto veloce, del pool di thread e
‫di come possiamo modificare la dimensione del
‫pool di thread , ok, tieni presente che
‫questo codice qui è
‫in realtà ancora asincrono, perché abbiamo passato una funzione di callback.
‫Ok, e potremmo effettivamente usare la versione sincrona, ma
‫ciò bloccherebbe il ciclo degli eventi.
‫Vuoi vederlo?
‫Quindi lascia che te lo mostri molto velocemente anche
‫a te, in modo che uno non
‫fosse davvero pianificato, ma facciamolo comunque, perché è
‫molto interessante vedere che penso.
‫Ok, quindi funzionerà così.
‫Usiamo ancora la versione di sincronizzazione della stessa funzione, che
‫una nota, è molte volte disponibile.
‫Ricorda che abbiamo lo stesso per il file letto,
‫quindi abbiamo letto file, che accetta una
‫richiamata, e abbiamo letto sincronia file, che è la versione
‫sincrona che non accetta alcuna richiamata, quindi proprio come questo.
‫Quindi questo crittograferà la password,
‫bloccherà l'esecuzione del codice e quindi passerà alla riga
‫successiva, che quindi registrerà questo qui nella console.
‫Quindi ora duplichiamo questo qui.
‫Era troppo, sbarazzati di questo qui, quindi
‫ora queste quattro crittografie della password non verranno più eseguite
‫nel ciclo degli eventi.
‫E quindi non verranno più scaricati nel pool di thread.
‫Ok, quindi ora, anche se abbiamo la dimensione del
‫pool di thread di quattro, vediamo cosa succede.
‫Quindi vedete, accadono completamente in modo sincrono.
‫Quindi uno dopo l'altro, e ciò che è anche
‫peggio, è che tutti questi
‫timer qui, anche NextTick e quello immediato,
‫sono apparsi solo dopo che è avvenuta la crittografia delle password.
‫Quindi questo stava davvero bloccando l'intera esecuzione, anche se
‫questo timer qui, per esempio questo qui,
‫è terminato dopo zero secondi e
‫questo dopo tre secondi,
‫ma tutti devono aspettare sette secondi prima
‫che tutte queste crittografie della password
‫qui siano finalmente pronti, sempre perché non erano in esecuzione all'interno
‫del ciclo degli eventi, ma lo erano.
‫E quindi stavano fondamentalmente lavorando in background e potevano
‫essere rilevati dal loop degli
‫eventi solo quando erano pronti, subito dopo
‫queste quattro crittografie della password, quindi questo è
‫stato un altro ottimo esempio di vedere il
‫blocco del codice e il loop degli eventi tutti in azione.
‫Ok, è stato abbastanza per una lezione, spero che
‫l'abbiate trovata interessante,
‫e ci vediamo alla prossima.