Promise, async/await e concorrenza controllata
Prerequisiti: lezioni 05, 07 e 12. Impara a distinguere un valore futuro dal lavoro che lo produce.
Definizioni
- Promise
- Un oggetto che rappresenta il futuro esito di un’operazione: pending mentre non è conclusa, fulfilled con un valore oppure rejected con un motivo. Una volta conclusa non cambia esito. Una Promise non è di per sé un thread e non rende ogni operazione non bloccante.
- async e await
- Una funzione async restituisce sempre una Promise. await sospende la continuazione di quella funzione fino all’esito, senza sospendere tutto il processo. Il codice sincrono prima e dopo l’attesa continua a usare il thread JavaScript.
- Composizione e fallimento
- Promise.all raccoglie i risultati nell’ordine degli input e fallisce al primo rifiuto osservato, ma non annulla automaticamente le altre operazioni. Promise.allSettled permette di ispezionare anche esiti parziali.
Esperimento riproducibile
Salva come concorrenza.mjs ed esegui node concorrenza.mjs. Non richiede pacchetti esterni.
import { setTimeout as pausa } from 'node:timers/promises';
async function lavoro(nome, durata) {
await pausa(durata);
return nome;
}
console.time('sequenza');
const a = await lavoro('A', 100);
const b = await lavoro('B', 100);
console.timeEnd('sequenza');
console.time('insieme');
const risultati = await Promise.all([
lavoro('A', 100), lavoro('B', 100)
]);
console.timeEnd('insieme');
console.log(a, b, risultati);Che cosa osservare
La sequenza impiega circa 200 ms; le attese avviate insieme circa 100 ms, con variazioni dovute al sistema. L’array finale mantiene A prima di B anche se cambi le durate. Non hai accelerato un calcolo: hai sovrapposto due attese indipendenti.
Errori e limiti
Metti try/catch intorno a un await quando puoi recuperare o aggiungere contesto. Una chiamata async non attesa può fallire dopo che il chiamante ha già terminato. Non avviare migliaia di richieste senza limite: memoria, connessioni e servizio remoto hanno capacità finite. Elabora piccoli gruppi o usa una coda di lavoro.
Prova tu
Fai fallire B e confronta all con allSettled. Poi aggiungi C e avvia al massimo due lavori per volta.
Criteri di verifica
Con all entra nel catch; A può continuare comunque. Con allSettled ottieni un risultato per ciascun input, con status fulfilled o rejected. Nei gruppi di due, C deve partire soltanto dopo il primo gruppo.
Riferimento: Promise nella documentazione Node.js.