3.1 Creazione di catene di promise
Le catene di promise permettono di eseguire in sequenza diverse operazioni asincrone, passando il risultato di un'operazione alla successiva. Questo rende il codice più leggibile e gestibile. Inoltre, le promise offrono potenti funzionalità per la gestione degli errori, consentendo di creare applicazioni affidabili e resilienti.
Concetto base
Una catena di promise si crea restituendo una nuova promise dal metodo then
. Ogni metodo then
restituisce una nuova promise, permettendo di costruire operazioni asincrone in sequenza.
Esempio di una semplice catena di promise
In questo esempio, ogni metodo then
esegue la sua operazione e passa il risultato al metodo then
successivo.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Step 1 completed');
}, 1000);
});
promise
.then((result) => {
console.log(result); // Mostrerà: Step 1 completed
return 'Step 2 completed';
})
.then((result) => {
console.log(result); // Mostrerà: Step 2 completed
return 'Step 3 completed';
})
.then((result) => {
console.log(result); // Mostrerà: Step 3 completed
})
.catch((error) => {
console.error(error);
});
Esempio di catena con operazioni asincrone
In questo esempio, ogni metodo then
attende il completamento dell'operazione asincrona prima di eseguire il passo successivo:
function asyncOperation(step) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`${step} completed`);
}, 1000);
});
}
asyncOperation('Step 1')
.then((result) => {
console.log(result); // Mostrerà: Step 1 completed
return asyncOperation('Step 2');
})
.then((result) => {
console.log(result); // Mostrerà: Step 2 completed
return asyncOperation('Step 3');
})
.then((result) => {
console.log(result); // Mostrerà: Step 3 completed
})
.catch((error) => {
console.error(error);
});
3.2 Gestione degli errori nelle catene di promise
Il metodo catch
viene utilizzato per la gestione degli errori nella catena di promise. Se si verifica un errore in una delle promise, viene passato al metodo catch
più vicino. Questo permette di gestire centralmente gli errori, migliorando la leggibilità e la manutenzione del codice.
Esempio di gestione degli errori
In questo esempio un errore avvenuto in Step 2
viene intercettato dal metodo catch
, e i successivi metodi then
non vengono eseguiti:
function asyncOperation(step, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(`${step} failed`);
} else {
resolve(`${step} completed`);
}
}, 1000);
});
}
asyncOperation('Step 1')
.then((result) => {
console.log(result);
return asyncOperation('Step 2', true); // Questa operazione fallirà
})
.then((result) => {
console.log(result); // Questo codice non verrà eseguito
return asyncOperation('Step 3');
})
.then((result) => {
console.log(result); // Questo codice non verrà eseguito
})
.catch((error) => {
console.error('Error:', error); // Mostrerà: Error: Step 2 failed
});
Gestione degli errori in passi specifici
A volte è necessario gestire gli errori in passi specifici della catena, senza interrompere l'intera catena. Per fare ciò si possono usare metodi then
e catch
nidificati.
Esempio di gestione degli errori in passi specifici
In questo esempio un errore in Step 2
viene gestito localmente, e la catena continua con un valore ripristinato:
function asyncOperation(step, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(`${step} failed`);
} else {
resolve(`${step} completed`);
}
}, 1000);
});
}
asyncOperation('Step 1')
.then((result) => {
console.log(result);
return asyncOperation('Step 2', true).catch((error) => {
console.warn('Handled error in Step 2:', error);
return 'Recovered from Step 2 error';
});
})
.then((result) => {
console.log(result); // Mostrerà: Recovered from Step 2 error
return asyncOperation('Step 3');
})
.then((result) => {
console.log(result); // Mostrerà: Step 3 completed
})
.catch((error) => {
console.error('Error:', error); // Questo codice non verrà eseguito
});
3.3 Utilizzo di finally
Il metodo finally
viene utilizzato per eseguire un codice indipendentemente dal fatto che la promise sia conclusa con successo o con un errore. È utile per eseguire azioni finali, come la pulizia delle risorse.
Esempio di utilizzo di finally:
function asyncOperation(step, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(`${step} failed`);
} else {
resolve(`${step} completed`);
}
}, 1000);
});
}
asyncOperation('Step 1')
.then((result) => {
console.log(result);
return asyncOperation('Step 2');
})
.then((result) => {
console.log(result);
return asyncOperation('Step 3');
})
.catch((error) => {
console.error('Error:', error);
})
.finally(() => {
console.log('All operations completed'); // Verrà eseguito in ogni caso
});
In questo esempio il metodo finally
viene eseguito in ogni caso, indipendentemente dal fatto che si sia verificato un errore o meno.
GO TO FULL VERSION