Federico Lelli / SchoolNode.js & Express
LEZIONE 29 · Affidabilità

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.

Materiali didattici curati e rielaborati da Federico Lelli. Le fonti e i riferimenti specifici sono indicati nei materiali disponibili.