Una Promise in JavaScript è un oggetto che rappresenta il risultato di un’operazione asincrona che potrebbe completarsi in futuro. È come una promessa: “Prometto di restituirti un risultato quando l’operazione sarà completata”. Una Promise può trovarsi in uno di questi tre stati:
- Pending (in sospeso): stato iniziale, non ancora completata o rifiutata.
- Fulfilled (completata): l’operazione è stata completata con successo.
- Rejected (rifiutata): l’operazione è fallita.
Perché usare le Promise?
Prima delle Promise, le callback venivano utilizzate per gestire l’asincronia. Tuttavia, l’annidamento di più callback portava al “Callback Hell”, rendendo il codice difficile da leggere e manutenere. Le Promise risolvono questo problema fornendo un modo per scrivere codice più chiaro e lineare, facilitando la gestione delle operazioni asincrone e il trattamento degli errori.
Guida all’uso delle Promise in JavaScript
Creare una Promise
Per creare una Promise, si utilizza new Promise
, passando una funzione executor con due parametri: resolve
e reject
. resolve
viene chiamato quando la Promise si completa con successo, reject
quando la Promise viene rifiutata.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Successo!');
} else {
reject('Errore!');
}
}, 1000);
});
In questo esempio, dopo 1 secondo, la Promise verrà completata con il risultato “Successo!” o rifiutata con “Errore!”.
Gestire il risultato con .then() e .catch()
Per ricevere il risultato di una Promise, si possono usare i metodi .then()
e .catch()
. .then(onFulfilled)
viene chiamato quando la Promise viene completata, .catch(onRejected)
quando la Promise viene rifiutata.
promise
.then((result) => {
console.log(result); // "Successo!"
})
.catch((error) => {
console.error(error); // "Errore!"
});
Concatenare le Promise (Chaining)
È possibile concatenare le Promise restituendo una Promise all’interno di .then()
.
firstPromise()
.then((result1) => {
return secondPromise(result1);
})
.then((result2) => {
console.log(result2);
})
.catch((error) => {
console.error(error);
});
Usare Promise.all
Promise.all
permette di eseguire più Promise in parallelo e ricevere i risultati quando tutte sono completate.
const promise1 = fetchData1();
const promise2 = fetchData2();
Promise.all([promise1, promise2])
.then(([result1, result2]) => {
console.log(result1, result2);
})
.catch((error) => {
console.error(error);
});
È importante gestire sempre gli errori usando .catch()
. Se si omette, gli errori potrebbero non essere rilevati e causare problemi difficili da debuggare.
Guida all’uso delle Promise in React
In React, spesso è necessario eseguire operazioni asincrone come chiamare API per ottenere dati. L’uso delle Promise aiuta a gestire queste operazioni in modo efficiente.
Usare fetch API con le Promise
fetch
è un’API integrata in JavaScript per ottenere dati e restituisce una Promise.
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error('Errore:', error);
});
In questo esempio, chiamiamo l’API a https://jsonplaceholder.typicode.com/users
per ottenere una lista di utenti.
Usare Promise, useEffect in un componente
import React, { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => {
setUsers(data);
})
.catch((error) => {
console.error('Errore:', error);
});
}, []);
return (
<div>
{users ? (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
) : (
<div>Caricamento...</div>
)}
</div>
);
}
export default UserList;
useEffect
con dipendenze vuote[]
verrà eseguito solo una volta quando il componente viene montato.- Si usa
fetch
per chiamare l’API e aggiornare lo statousers
quando si riceve il risultato.
Confronto tra Promise e Async/Await
Async/Await è una nuova sintassi basata sulle Promise, che rende il codice più simile al codice sincrono, più leggibile e comprensibile. Utilizza try...catch
per la gestione degli errori ed evita l’annidamento eccessivo di .then()
. Tuttavia, l’uso di Async/Await richiede una buona comprensione delle Promise. Usare Async/Await quando si desidera un codice simile al sincrono, più leggibile e si ha bisogno di eseguire operazioni asincrone in sequenza. Usare Promise quando si ha bisogno di gestire più operazioni asincrone contemporaneamente e si necessita di metodi come Promise.all
, Promise.race
.