Classe Promise in JavaScript

Classe Promise in JavaScript

In questo articolo, spieghiamo la classe Promise in JavaScript.

YouTube Video

Promise

La classe Promise è una classe per gestire operazioni asincrone. Gestisce i risultati se l'operazione ha successo o gestisce errori se fallisce. Tradizionalmente, venivano utilizzate le funzioni di callback per aspettare la conclusione di un'operazione asincrona, ma Promise rende questo processo più chiaro e potente.

1const promise = new Promise((resolve, reject) => {
2    setTimeout(() => resolve("Done!"), 1000);
3});
4
5// Displays "Done!" after 1 second
6promise.then(result => console.log(result));
  • Questo codice è un esempio di un processo asincrono che mostra "Fatto!" dopo un secondo.
    • Per prima cosa, viene creato un nuovo oggetto Promise usando new Promise. L'argomento è una funzione che accetta due callback: resolve per il successo e reject per il fallimento.
    • Si usa setTimeout per chiamare resolve() dopo un secondo.
    • Il metodo then() dell'oggetto promise attende il completamento e visualizza il risultato.

Struttura di base

Un Promise è un oggetto che alla fine si conclude con successo o fallimento.

 1const promise = new Promise((resolve, reject) => {
 2    // Asynchronous operation
 3    // Flag indicating whether the operation was successful
 4    const success = true;
 5
 6    if (success) {
 7        resolve('Operation successful!');
 8    } else {
 9        reject('An error occurred');
10    }
11});
  • In caso di successo, viene chiamato resolve().
  • In caso di fallimento, viene chiamato reject().

L'oggetto Promise ha tre stati.

1promise
2    .then((result) => {
3        console.log(result);
4    })
5    .catch((error) => {
6        console.error(error);
7    })
  • In attesa
    • Il processo asincrono non è ancora stato completato.
  • Completato
    • Il processo asincrono è riuscito e il risultato è stato restituito da resolve(). Il risultato viene ricevuto usando il metodo then().
  • Rifiutato
    • Il processo asincrono è fallito ed è stato generato un errore tramite reject(). L'errore viene ricevuto usando il metodo catch().

Metodi then() e catch()

Utilizzando una Promise, è possibile definire cosa fare quando un'operazione asincrona si completa. Per questo, si utilizzano i metodi then() e catch().

then()

1const promise = new Promise((resolve, reject) => {
2    resolve('Operation successful!');
3});
4
5promise.then((result) => {
6    console.log(result);  // "Operation successful!"
7});
  • Il metodo then() specifica una funzione da chiamare quando la Promise ha successo.

catch()

1const promise = new Promise((resolve, reject) => {
2    reject('An error occurred');
3});
4
5promise.catch((error) => {
6    console.error(error);  // "An error occurred"
7});
  • Il metodo catch() specifica una funzione da chiamare quando la Promise fallisce.

Metodo finally()

 1const promise = new Promise((resolve, reject) => {
 2    resolve('Operation successful!');
 3});
 4
 5promise
 6    .then((result) => {
 7        console.log(result);
 8    })
 9    .catch((error) => {
10        console.error(error);
11    })
12    .finally(() => {
13        console.log('The operation has completed');
14    });
  • Il metodo finally() definisce il codice che verrà eseguito alla fine, indipendentemente dal successo o fallimento della Promise.

then() Catena

then() restituisce una nuova Promise, quindi puoi catenare il prossimo then().

 1const promise = new Promise((resolve, reject) => {
 2    setTimeout(() => {
 3        resolve(1);
 4    }, 1000);
 5});
 6
 7promise
 8    .then(result => {
 9        console.log(result); // 1
10        return result + 1;
11    })
12    .then(result => {
13        console.log(result); // 2
14        return result + 1;
15    })
16    .then(result => {
17        console.log(result); // 3
18    })
19    .catch(error => {
20        console.error(error.message); // Something went wrong
21    });
  • In questo codice, il resolve() iniziale passa il valore 1 e ogni valore restituito da un then viene passato al prossimo then.
  • Usando catch(), puoi gestire in un solo posto qualsiasi errore che si verifichi nella catena.

Esempio Pratico

Ad esempio, i Promises vengono spesso utilizzati per recuperare dati da un server. Vediamo un esempio utilizzando l'API fetch().

 1fetch('https://codesparklab.com/json/example.json')
 2    .then(response => {
 3        if (!response.ok) {
 4            throw new Error('Network error');
 5        }
 6        return response.json();
 7    })
 8    .then(data => {
 9        console.log(data);
10    })
11    .catch(error => {
12        console.error('Error:', error);
13    });
  • In questo codice, poiché fetch() restituisce un Promise, viene utilizzato then() per elaborare i dati dopo aver ricevuto una risposta dal server. Gli errori vengono gestiti utilizzando catch().

Gestione di Promesse Multiple

Promise.all()

Per eseguire più Promises contemporaneamente e procedere solo se tutte hanno successo, utilizza Promise.all().

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.resolve(2);
 3const promise3 = Promise.resolve(3);
 4
 5Promise.all([promise1, promise2, promise3])
 6    .then((results) => {
 7        console.log(results);  // [1, 2, 3]
 8    })
 9    .catch((error) => {
10        console.error('Error :', error);
11    });
  • then() viene chiamato solo se tutte le Promises hanno successo. catch() viene chiamato se anche solo una fallisce.

Promise.allSettled()

Se vuoi eseguire più Promise simultaneamente e ottenere tutti i risultati indipendentemente dal successo o dal fallimento, usa Promise.allSettled().

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.reject("Failed");
 3const promise3 = Promise.resolve(3);
 4
 5Promise.allSettled([promise1, promise2, promise3])
 6    .then((results) => {
 7        results.forEach(result => console.log(result));
 8        // [
 9        //   { status: 'fulfilled', value: 1 },
10        //   { status: 'rejected', reason: 'Failed' },
11        //   { status: 'fulfilled', value: 3 }
12        // ]
13    });
  • then() viene chiamato una volta che tutte le Promise sono state risolte (sia soddisfatte che rifiutate). Ogni risultato include una proprietà status ('fulfilled' o 'rejected'). Anche se alcune falliscono, non influisce sulle altre operazioni.

Promise.race()

Promise.race() restituisce il risultato della Promise che si risolve per prima, sia che venga completata sia che venga rifiutata.

1const promise1 = new Promise((resolve) => setTimeout(resolve, 100, 'First'));
2const promise2 = new Promise((resolve) => setTimeout(resolve, 500, 'Second'));
3
4Promise.race([promise1, promise2]).then((result) => {
5    console.log(result);  // "First"
6});
  • Come in questo esempio, viene restituito il risultato del primo Promise completato.

Relazione con async/await

Utilizzando la sintassi async/await è possibile scrivere Promises in modo più intuitivo. Una funzione async restituisce sempre un Promise e await attende che il Promise venga risolto.

 1async function fetchData() {
 2    try {
 3        const response = await fetch('https://codesparklab.com/json/example.json');
 4        const data = await response.json();
 5        console.log(data);
 6    } catch (error) {
 7        console.error('Error :', error);
 8    }
 9}
10
11fetchData();

Utilizzando async/await in questo modo, le operazioni asincrone possono essere scritte come codice sincrono, rendendolo più facile da leggere.

Riepilogo

  • Promise è un oggetto per gestire il successo o il fallimento delle operazioni asincrone.
  • Gestisci le operazioni di successo con then() e gli errori con catch().
  • finally() definisce il codice che viene eseguito alla fine indipendentemente dal successo o dal fallimento.
  • Puoi gestire più Promises insieme utilizzando Promise.all() o Promise.race().
  • async/await è una sintassi per scrivere i Promises in modo più semplice.

Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.

YouTube Video