Introduzione alle promesse
Una promessa è comunemente definita come un proxy per un valore che alla fine diventerà disponibile.
Le promesse sono un modo per gestire il codice asincrono, senza rimanere bloccati nell’inferno di callback.
Le promesse sono state parte del linguaggio per anni (standardizzate e introdotte in ES2015) e recentemente sono diventate più integrate, con async e await in ES2017.,
Le funzioni asincrone utilizzano le promesse dietro le quinte, quindi capire come funzionano le promesse è fondamentale per capire come funzionanoasync
eawait
.
Come funzionano le promesse, in breve
Una volta che una promessa è stata chiamata, inizierà in uno stato in sospeso. Ciò significa che la funzione chiamante continua l’esecuzione, mentre la promessa è in sospeso fino a quando non si risolve, dando alla funzione chiamante qualsiasi dato fosse richiesto.,
La promessa creata finirà in uno stato risolto, o in uno stato rifiutato, chiamando le rispettive funzioni di callback (passate athen
ecatch
) al termine.
Quali API JS utilizzano le promesse?
Oltre al proprio codice e al codice delle librerie, le promesse vengono utilizzate dalle API Web moderne standard come:
- l’API della batteria
- l’API Fetch
- Addetti ai servizi
È improbabile che nel JavaScript moderno ti ritrovi a non usare le promesse, quindi iniziamo a immergerti direttamente in esse.,
Creazione di una promessa
La Promessa API espone una Promessa costruttore, che si inizializza l’utilizzo di new Promise()
:
Come si può vedere, la promessa di controlli done
costante globale, e se questo è vero, la promessa va a uno stato risolto (visto che il resolve
callback è stato chiamato); in caso contrario, il reject
callback viene eseguito, mettendo la promessa in un stato rifiutato., (Se nessuna di queste funzioni viene chiamata nel percorso di esecuzione, la promessa rimarrà in uno stato in sospeso)
Usando resolve
e reject
, possiamo comunicare al chiamante quale fosse lo stato della promessa risultante e cosa fare con esso. Nel caso precedente abbiamo appena restituito una stringa, ma potrebbe essere un oggetto, o anche null
. Poiché abbiamo creato la promessa nello snippet sopra, è già stata avviata l’esecuzione. Questo è importante per capire cosa sta succedendo nella sezione Che consuma una promessa qui sotto.,
Un esempio più comune che potresti incontrare è una tecnica chiamata Promisifying. Questa tecnica è un modo per essere in grado di utilizzare una classica funzione JavaScript che accetta un callback e restituisce una promessa:
Nelle versioni recenti di Node.js, non dovrai fare questa conversione manuale per molte delle API. C’è una funzione promisifying disponibile nel modulo util che lo farà per te, dato che la funzione che stai promisifying ha la firma corretta.,
Consumare una promessa
Nell’ultima sezione, abbiamo introdotto come viene creata una promessa.
Ora vediamo come la promessa può essere consumata o utilizzata.
L’esecuzione di checkIfItsDone()
specificherà le funzioni da eseguire quando la promessa isItDoneYet
si risolve (nella chiamata then
) o rifiuta (nella chiamata catch
).
Promesse concatenate
Una promessa può essere restituita a un’altra promessa, creando una catena di promesse.,
Un ottimo esempio di concatenamento delle promesse è l’API Fetch, che possiamo usare per ottenere una risorsa e mettere in coda una catena di promesse da eseguire quando la risorsa viene recuperata.
L’API Fetch è un meccanismo basato sulla promessa e chiamarefetch()
equivale a definire la nostra promessa usandonew Promise()
.
Esempio di concatenamento delle promesse
In questo esempio, chiamiamofetch()
per ottenere un elenco di elementi TODO dal filetodos.json
trovato nella radice del dominio e creiamo una catena di promesse.,
Esecuzione fetch()
restituisce una risposta, che ha molte proprietà, e all’interno di quelle che abbiamo di riferimento:
-
status
, un valore numerico che rappresenta il codice di stato HTTP -
statusText
, un messaggio di stato, che èOK
se la richiesta è riuscito
response
anche un json()
metodo che restituisce una promessa che verrà risolto con il contenuto del corpo elaborati e trasformati in JSON.,
Quindi, date queste premesse, questo è ciò che accade: la prima promessa nella catena è una funzione che abbiamo definito, chiamatastatus()
, che controlla lo stato della risposta e se non è una risposta di successo (tra 200 e 299), rifiuta la promessa.
Questa operazione farà sì che la catena di promesse salti tutte le promesse concatenate elencate e salterà direttamente all’istruzionein basso, registrando il testoRequest failed
insieme al messaggio di errore.,
Se invece riesce, chiama la funzione json()
che abbiamo definito. Poiché la promessa precedente, quando ha avuto successo, ha restituito l’oggettoresponse
, lo otteniamo come input per la seconda promessa.
In questo caso, restituiamo i dati JSON elaborati, quindi la terza promessa riceve direttamente il JSON:
.then((data) => { console.log('Request succeeded with JSON response', data)})
e lo registriamo semplicemente alla console.
Gestione degli errori
Nell’esempio, nella sezione precedente, abbiamo avuto uncatch
che è stato aggiunto alla catena di promesse.,
Quando qualcosa nella catena di promesse fallisce e genera un errore o rifiuta la promessa, il controllo va all’istruzione più vicina lungo la catena.
Errori a cascata
Se all’interno disi genera un errore, è possibile aggiungere un secondo per gestirlo e così via.
new Promise((resolve, reject) => { throw new Error('Error')}) .catch(err => { throw new Error('Error') }) .catch(err => { console.error(err) })
Orchestrare le promesse
Promessa.,all()
Se hai bisogno di sincronizzare diverse promesse, Promise.all()
ti aiuta a definire un elenco di promesse ed eseguire qualcosa quando sono tutte risolte.
Esempio:
La sintassi di assegnazione destrutturazione ES2015 consente di eseguire anche
Promise.all().then(() => { console.log('Results', res1, res2)})
Non si è limitati a utilizzarefetch
naturalmente, qualsiasi promessa può essere utilizzata in questo modo.
Promessa.,race()
Promise.race()
viene eseguito quando si risolve la prima delle promesse che si passano e viene eseguito il callback allegato solo una volta, con il risultato della prima promessa risolta.,
Esempio:
errori Comuni
Uncaught TypeError: undefined non è una promessa
Se si ottiene il Uncaught TypeError: undefined is not a promise
errore nella console, assicurarsi di che utilizzare new Promise()
invece di Promise()
UnhandledPromiseRejectionWarning
Questo significa che una promessa è chiamato respinto, ma non c’era catch
utilizzato per gestire l’errore. Aggiungi un catch
dopo l’offesothen
per gestirlo correttamente.