Articolo originale: https://www.freecodecamp.org/news/javascript-es6-promises-for-beginners-resolve-reject-and-chaining-explained/

Le Promise sono uno dei modi per gestire le operazioni asincrone in JavaScript. Molte persone fanno fatica a comprendere il funzionamento delle Promise, quindi in questo articolo cercherò di spiegarle nel modo più semplice possibile.

Le Promise sono un argomento molto vasto e in questo articolo non potrò affrontare ogni dettaglio, ma ti fornirò un'introduzione generale su cosa sono le Promise, spiegazioni di termini come resolve, reject e concatenamento, e un esempio di codice per creare e usare delle Promise.

Prerequisiti: per capire meglio questo articolo, dai un'occhiata al mio articolo sulle funzioni callback in JavaScript.

Cos'è una Promise?

Una Promise in JavaScript è simile a una promessa nella vita reale. Quando facciamo una promessa nella vita reale, è garantito che faremo qualcosa in futuro. Infatti le promesse possono essere fatte solo per il futuro.

Una promessa ha due possibili risultati: quando arriva il momento, può essere mantenuta oppure no.

Questo vale anche per le Promise in JavaScript. Definiamo una Promise e quando arriva il momento, sarà risolta oppure rifiutata.

Promise in JavaScript

Prima di tutto, una Promise è un oggetto. Esistono 3 stati di un oggetto Promise:

  • Pending (in attesa): stato iniziale, prima che la Promise abbia successo o fallisca
  • Resolved (risolta): Promise completata
  • Rejected (rifiutata): Promise fallita
image
Rappresentazione del processo di una Promise

Ad esempio, quando richiediamo dei dati da un server usando una Promise, questa resterà nello stato pending fino alla ricezione dei dati.

Se otteniamo le informazioni dal server, la Promise sarà risolta con successo (resolved). Se invece non otteniamo le informazioni, allora la Promise sarà nello stato rejected.

In aggiunta, se esistono più richieste, dopo la che la prima Promise viene risolta (o rifiutata), inizierà un nuovo processo che può essere accodato direttamente grazie a un metodo chiamato concatenamento (chaining).

Che differenza c'è tra callback e Promise?

La differenza principale tra funzioni callback e Promise è che possiamo accodare una funzione callback a una Promise, piuttosto che passarla al suo interno. Quindi anche con le Promise facciamo uso di funzioni callback, ma in un modo diverso, grazie al concatenamento.

Questo è uno dei vantaggi maggiori dell'usare le Promise, ma perché?

Cos'è il concatenamento?

Le funzioni callback sono state usate da sole per le operazioni asincrone in JavaScript per molti anni. Ma in alcuni casi, usare le Promise può essere un'opzione migliore.

Se occorre effettuare più operazioni asincrone e proviamo a usare le care, vecchie funzioni callback, ci troveremo velocemente in una situazione chiamata callback hell (inferno callback):

primaRichiesta(function(risposta) {  
    secondaRichiesta(risposta, function(rispostaSuccessiva) {    
        terzaRichiesta(rispostaSuccessiva, function(rispostaFinale) {     
            console.log('Risposta finale: ' + rispostaFinale);    
        }, callbackFallimento);  
    }, callbackFallimento);
}, callbackFallimento);

Tuttavia, se gestiamo le stesse operazioni con le Promise, dato che possiamo accodare le callback invece di passarle come argomenti, stavolta otterremo un codice più pulito e leggibile:

primaRichiesta()
  .then(function(risposta) {
    return secondaRichiesta(risposta);
}).then(function(rispostaSuccessiva) {  
    return terzaRichiesta(rispostaSuccessiva);
}).then(function(rispostaFinale) {  
    console.log('Risposta finale: ' + rispostaFinale);
}).catch(callbackFallimento);

Il codice qui sopra mostra come più callback possono essere concatenate una dopo l'altra. Il concatenamento è una delle caratteristiche migliori delle Promise.

Creare e usare una Promise

Prima di tutto, usiamo un costruttore per creare un oggetto Promise:

const myPromise = new Promise();

Accetta due parametri, uno per il successo (resolve) e uno per il fallimento (reject):

const myPromise = new Promise((resolve, reject) => {  
    // condizione
});

Infine, dovremo aggiungere una condizione. Se la condizione si verifica, la Promise sarà risolta, altrimenti sarà rifiutata:

const myPromise = new Promise((resolve, reject) => {  
    let condizione;  
    
    if(condizione è vera) {    
        resolve('Promise risolta con successo.');  
    } else {    
        reject('Promise rifiutata');  
    }
});

Abbiamo creato la nostra prima Promise. Adesso usiamola.

then( ) per le Promise risolte:

Se torni alla figura all'inizio dell'articolo, vedrai che ci sono due casi: uno per le promise risolte e uno per quelle rifiutate. Se la Promise viene risolta (il caso di successo), allora qualcosa accadrà successivamente (in base a cosa vogliamo fare con una Promise risolta con successo).

myPromise.then();

Il metodo then() viene chiamato dopo che la Promise è risolta. Poi possiamo decidere cosa fare in questo caso.

Ad esempio, mostriamo sulla console il messaggio che otteniamo dalla Promise:

myPromise.then((messaggio) => {  
    console.log(messaggio);
});

catch( ) per le Promise rifiutate:

Tuttavia, il metodo then() è soltanto per le Promise risolte. E se una Promise fallisce? In questo caso dobbiamo usare il metodo catch().

Proprio come abbiamo accodato il metodo then(), possiamo aggiungere direttamente il metodo catch() dopo di esso:

myPromise.then((messaggio) => { 
    console.log(messaggio);
}).catch((messaggio) => { 
    console.log(messaggio);
});

Quindi, se la Promise viene rifiutata, salteremo al metodo catch() e stavolta vedremo un messaggio diverso sulla console.

Conclusione

E così abbiamo creato una Promise in JavaScript e l'abbiamo usata per i casi resolve e reject. Le Promise sono un argomento vasto e ci sono molte altre cose da imparare a riguardo. Imparare come funzionano richiede del tempo.

Questa è solo un'introduzione alle Promise e spero che tu l'abbia trovata utile per farti un'idea di cosa sono le Promise e di come usare in JavaScript.

Grazie per aver letto questo articolo!