I generatori in JavaScript

In questo video parleremo dei generatori. Essi esistono anche in altri linguaggi di programmazione e con l'ECMAScript 6 sono stati introdotti anche da JavaScript.
I generatori sono delle funzioni speciali, che a differenza di eseguire tutto il codice al loro interno in un colpo solo, come in una normale funzione, ne eseguono solo una specifica parte. Quindi un generatore al suo interno ha il codice suddiviso in diverse porzioni, delimitate dalla nuova keyword yield e attraverso il metodo next() possiamo far eseguire al generatore la parte che ci interessa nel momento più opportuno. Una volta eseguita quella parte di codice, il generatore si rimette in pausa finchè noi non andremo a richiedere un'altra parte di codice riutilizzando il metodo next().
Anche se i generatori possono essere utilizzati in diversi scenari, essi nascono per lavorare con le promise e quindi sono stati ideati per maneggiare codice asincrono.
Sfortunatamente non sono semplicissimi da implementare e specialmente all'inizio non è facile capirne il funzionano. Per questo motivo l'ECMAScript 8 ha introdotto le funzioni asincrone, che eseguono lo stesso lavoro dei generatori però con una sintassi estremamente semplificata, lasciando l'uso dei generatori solo a chi ha esigenze molto particolari.
Abbiamo già parlato delle Promise e delle funzioni asincrone rispettivamente nel video sez8/2 e sez8/4.

Trascrizione: (click per espandere)
salve a tutti in questo video parlerò
dei generatori un'importante novità
introdotta con l'ecmascript sei un
generatore è come una funzione però un
po' speciale
a differenza di una funzione normale in
cui quando viene invocata esegue in un
sol colpo tutto il codice il suo interno
un generatore può eseguire il codice del
suo interno in piccole parti o meglio
ogni volta che io invoco il mio
generatore e gli faccio seguire una
parte del codice suo interno per dire al
generatore esegui questa parte e poi
fermati all'interno di un generatore io
andrò a usare di una nuova keyword che
si chiama yield andiamo a vedere come si
scrive un generatore allora si usa la
keyword function poi si mette un
asterisco e l'asterisco fa capire
javascript e guarda che sto scrivendo
creando un generatore e poi gli si dà un
nome come qualsiasi altra funzione
parentesi tonde parentesi graffe adesso
andiamo a vedere allora come vi dicevo
all'interno di un generatore si può
usare la keyword yield la keyword yield
vuol dire e eseguì il codice all'interno
vi faccio vedere
inizio tanto per far vedre poi qui
metto questa keyword yield poi qui metto
parola 1 una stringa giusto per fare
vedere poi vi faccio mettere un altro
console.log in mezzo e poi metto un altro yield
e qua metto parola 2 e poi ci metto un'altra
console.log fine ecco qui allora cosa cosa
vado a fare qui voglio dire a javascript
adesso quando andrò a invocare questo
generatore esegui tutto il codice fino
alla prima yield che trovi
quindi mi verrà eseguito questo codice
qui e questo codice qui anzi qui invece
di metterci una stringa ci mette un
operazione giusto per meglio poi alla
seconda volta che andrò a invocare
questo generatore dico esegui
tutto il codice
dopo il primo yield però fino al secondo yield
quindi mi eseguirà questo codice qui e
poi questo codice qui e poi vedremo cosa
succede quando io andrò a evocarlo per
la terza volta
allora come si invoca un
generatore allora io creo una costante e
la chiamo risultato 1 e vado a invocare
generatore 1 ecco qui adesso io salvo e
non succede niente console.log non succede
niente perché perché quando io invoco il
generatore
io non sto dicendo al generatore ok
comincia eseguire il tuo codice
io sto solo dicendo generatore preparati
perché adesso andrò a invocare a
invocarti di nuovo però andro' ad invocarti
solo fino al primo yield
come faccio a dire a generatore ok ti
reinvoco si usa un metodo che si chiama
next
allora vi faccio vedere ok risultato
1
e allora metto risultato 1 che è
questa qui next e adesso se io
salvo
come vedete io
ho eseguito il codice all'interno del
generatore la mia prima riga di che è
inizio e poi ho eseguito anche se al
momento non lo vedo ho eseguito anche
questo questo qui mi viene ritornato
sotto forma di oggetto che ha due
proprietà la proprietà un valore la
proprietà "value" quindi che sarà il
valore questo valori qui e poi un'altra
proprietà che sarà done che vuol dire che
ha un valore booleano vero falso che
vuol dire ok
il tutto il codice all'interno del
generatore è stato eseguito oppure no il
con tutto il codice all'interno del
generatore non è ancora stato eseguito
completamente vi faccio vedere console.log risultato 1 eccolo qui come vedete allora il
valore 3 + 5 e' 8 e poi di che mi dice
guarda che il codice all'interno del
generatore non è ancora finito quindi è
falso
andiamo a vedere cosa succede se io l'ho
reinvoco un'altra volta
allora metto r2 cosa mi devo aspettare
mi aspetterò che mi venga eseguito tutto
il codice dal primo yield fino al
secondo yield quindi mi verrà eseguito
questo console.log e poi mi verrà anche
ritornato questo valore qui andiamo a
vedere eccolo qui adesso io c'ho in mezzo
eccolo qui e poi avrò ancora parola 2 e
poi come vedete il codice mi dice c'e'
ancora codice da eseguire
dentro il mio generatore come faccio a
eseguire tutto il mio codice
ecco qui e lo facciamo console.log 3
ecco qua adesso come vedete siccome non
c'è più yield mi verra' ritornato indefinito però mi
pero' dice anche guarda che non c'è più
codice da eseguire all'interno del tuo
generatore quindi mi dice done true
avrei potuto anche metterci un return
dentro qui ritorno me diciamo che
ritorno
facciamo che ritorno 100
ecco qua e come vedete non ho yield che
mi ritorna un valore uso la keyword
return per ritornare cento
però comunque il codice è finito e
quindi ho valore 100 e done vero quindi non
c'è più il codice da eseguire vi faccio
vedere un altro esempio leggermente
più complesso sempre di un generatore
allora function asterisco abbiamo detto
generatore 2 e cominciamo allora diciamo
che io voglio passarci un parametro lo
chiamò un parametro x e voglio anche
fare bloccare il mio generatore e far
ritornare il parametro che ho inserito
adesso andiamo a invocare const risultato
due generatore 2 abbiamo detto e quando
io invoco siccome qui si aspetta un
argomento gli passò mettiamo 10 poi io
vi faccio subito vedere
l'output console.log
ris 2 next
ecco qui andiamo a vedere
eccolo qua lui mi ritorna il valore che
ho passato quando ho invocato il mio
generatore
eccolo qua valore 10 done false
perché io sono fermo qui quindi io non
so se dopo questo yield c'è ancora codice
oppure no
diciamo che adesso io ci aggiungo ancora un po' di codice facciamo un po' particolare
const la chiamo numero uguale a 5 più yield e questo facciamo x + 1
e qua complichiamo un po' la faccenda cosa succede qua allora io adesso quando andrò a
chiamare il mio generatore per la
seconda volta come sempre dico esegui
tutto il codice fino al prossimo yield
quindi questo qui questo codice qui fino
a questo yield è stato eseguito da questo
next e poi con questo next io dico ok
vai a eseguire altro codice mi verrà
eseguito questo codice qui fino a questo
yield qua questo codice
cos'è è l'argomento
passato quando ha invocato la mia
funzione più uno quindi sarà valore 11
done false andiamo a vedere qui valore
11 done false e al momento il mio
generatore fermo qui se io adesso voglio
andare a continuare il codice
all'interno del mio generatore posso
fare per esempio così yield e ritorno
numero richiamo il mio generatore per la
terza volta quindi mi verrà eseguito il
codice adesso il generatore fermo qui mi
verrà eseguito il codice da qui fino a
qui
quando io vado a invocare questo next
qui siccome
questo yield qua viene usato dentro questa
espressione qua io posso passarci un
numero o meglio possono passarci un
argomento metto 50 quindi quando io
invochero' per la terza volta il mio
generatore questo qui sarà come se fosse
un 50 quindi 50 + 5 mi aspetto 55 andiamo a vedere
done false perché ancora io sono fermo qui e non so cosa c'è dopo questo yield in
questo caso non c'è niente quindi adesso
io quando farò vedere quando invocherò
per la terza volta mi verra' indefinito
ed indefinito done true ok adesso vi faccio
vedere un esempio in cui può essere
utile usare un generatore un esempio
molto banale function 3 e diciamo che io
crea un generatore 3 e diciamo che io
voglio usare questo generatore per
creare degli id univoci magari id che
posso associare a degli oggetti per
distinguere gli oggetti perché se io
creo oggetti tutti uguali
posso associarci un id che identifica un
oggetto per esempio l'oggetto 1 l'oggetto 2 l'oggetto 3 e così posso distinguere i vari
oggetti quando sono tutte uguali
come faccio a fare questo per esempio
posso creare una variabile la chiamo id
e le assegna uno 0 e poi creo un ciclo
while gli passò un vero dentro qui
quindi sarà sempre vero
e poi dentro ci metto yield e ritorno
è il mio id++ cosa succede qui
se mettete questo codice dentro una
funzione normale vi andrà in un loop
infinito perché il while è sempre vero
però avendo io
la keyword yield qua vado ad eseguire
questo loop che sarebbe infinito solo
quando lo voglio io e per un'interazione
perchè poi alla seconda interazione si
ribloccherà perche' ritroverà lo yield
andiamo a vedere come funziona allora
const risultato 3 diciamo quindi il
generatore 3 e poi facciamo un po' di
console log allora risultato 3 next
allora il primo sarà uno 0
eccolo qui valore zero però se io ne
prendo un po' questo qua allora abbiamo detto
che e' 0 poi questo sarà 1 perché sarà la
seconda interazione del mio while poi ci
sarà il 2
se adesso io né stampo altri tre per
esempio ecco qua 012345 come
vedete io posso invocare un loop che
sarebbe infinito però proprio perché sto
usando il mio yield al suo interno sono
io che gestisco le iterazioni del loop
ok allora avete visto un'introduzione ai
generatori voi potrete pensare va beh mi
sembra che non facciano niente di
particolare io vi dico beh visti così
avete anche ragioni però i generatori
sono stati ideati diciamo per lavorare
con le promesi
se voi pensate a una serie di promesi
che devono essere eseguite una dopo
l'altra e poi pensate al generatore che
esegue codice quando richiesto
voi potete pensare ok la promesi è stata la prima promesi è stata
risolta fai partire la seconda promesi
generatore fai partire la seconda poi
la seconda stata risolta ok fai partire
la terza se la vedete così potete provare a
capire come potrebbero lavorare insieme
generatori e promesi non ve lo farò
vedere in quanto richiede
un livello di javascript e un po' più
complesso di quello base e quindi
sarebbe un po' fuori da questo tutorial
infatti questo tutorial parla
di javascript a livello di iniziare a
programmare con javascript però vi metto
un link in descrizione in cui potete
trovare tutte le informazioni che vi
servono sui generatori e come usarle per
lavorare con javascript
inoltre non vi faccio neanche un altro
motivo per cui non ve lo faccio vedere è
perché vi ho già fatto vedere come si
possono usare le funzioni asincrone
insieme alle promesi per lavorare con
loro
e diciamo che per una buona parte del
lavoro che può essere fatto con le
promesi basta usare le funzioni
asincrone bastano e avanzano è sono più semplici che usare i
generatori
se poi voi avete
necessità
particolari e dovete manipolare promise
e oppure abortire eventuali promise
eccetera loro in poi caso dovrete usare
i generatori però appunto si parla di un
livello di javascript un po' più alto
comunque con questo è tutto a un'altra
cosa che non vi ho detto vabbè i
generatori possono essere innestati
dentro altri generatori basta mettere
per esempio una yield con l'asterisco e
potete andare a
lavorare con generatori innestati ad
altri generatori
con questo è tutto ci sentiamo alla
prossima ciao
File del video: