W3docs

Promise JavaScript

Impara le Promise JavaScript: stati pending, fulfilled e rejected, la funzione executor con resolve e reject, then/catch/finally e la coda delle microtask, con esempi eseguibili.

Le Promise in JavaScript sono uno strumento potente per gestire le operazioni asincrone, che consente agli sviluppatori di scrivere codice più pulito e robusto. Questo capitolo spiega cos'è una promise, i tre stati in cui può trovarsi, come funziona la funzione executor con resolve e reject, come consumare i risultati con .then, .catch e .finally, e quando i callback delle promise vengono effettivamente eseguiti (la coda delle microtask). Comprendere questi fondamentali è essenziale prima di passare al chaining, alla Promise API e all'async/await.

Introduzione alle Promise JavaScript

Una Promise è un object che rappresenta un valore che potrebbe non essere ancora disponibile, ma lo sarà in un momento futuro. Invece di passare un callback a una funzione asincrona sperando che venga chiamato, si riceve immediatamente un object promise al quale si allegano i callback. Questo evita i callback profondamente annidati, spesso chiamati "callback hell", e fornisce un modo unico e coerente per gestire sia il successo che il fallimento.

Un tipico compito asincrono — una richiesta di rete, un timer, la lettura di un file — non ha il suo risultato pronto immediatamente. La promise è un segnaposto per quel risultato.

I Tre Stati di una Promise

Una promise si trova sempre in esattamente uno dei tre stati:

  • pending — lo stato iniziale; l'operazione non è ancora completata.
  • fulfilled — l'operazione è completata con successo e la promise ha un valore.
  • rejected — l'operazione è fallita e la promise ha un motivo (solitamente un Error).

Una promise pending può passare allo stato fulfilled o rejected. Una volta fatto, è settled e non può mai cambiare stato di nuovo. Questa transizione unidirezionale e unica è ciò che rende le promise prevedibili: un callback .then collegato a una promise già fulfilled verrà comunque eseguito, e una promise non può mai passare da fulfilled a rejected.

                  ┌─────────────┐  resolve(value)   ┌─────────────┐
                  │   pending   │ ────────────────▶ │  fulfilled  │
   new Promise ─▶ │             │                   └─────────────┘
                  │             │  reject(reason)   ┌─────────────┐
                  └─────────────┘ ────────────────▶ │  rejected   │
                                                    └─────────────┘

Creare una Promise

Per creare una promise, si chiama il costruttore Promise passandogli una funzione chiamata executor. L'executor viene eseguito immediatamente e in modo sincrono nel momento in cui la promise viene creata. Riceve due funzioni come argomenti, convenzionalmente chiamate resolve e reject:

  • Chiama resolve(value) per portare la promise allo stato fulfilled con value.
  • Chiama reject(reason) per rigettare la promise con reason.

Finché non si chiama una di esse, la promise rimane pending.


javascript— editable

L'executor riceve resolve e reject in modo da poter risolvere la promise una volta terminato il lavoro asincrono. Qui la promise diventa fulfilled dopo un timer di un secondo:


javascript— editable

Nota: Solo la prima chiamata a resolve o reject è rilevante. Una volta che una promise è settled, qualsiasi ulteriore chiamata a resolve o reject viene ignorata. Inoltre, se l'executor genera un errore in modo sincrono, la promise viene automaticamente rigettata con quell'errore.

Gestire i Risultati con .then, .catch e .finally

Una volta creata una promise, se ne consuma il risultato con i metodi .then, .catch e .finally. Questi sono il modo in cui il resto del codice reagisce a una promise settled.

Il metodo then

Il metodo .then viene usato per programmare un callback da eseguire quando la promise è fulfilled. Affinché una promise sia fulfilled, deve essere chiamato il metodo resolve. L'argomento passato al metodo resolve sarà il valore finale della promise.


javascript— editable

In questo codice, la promise sarà fulfilled solo dopo che il timeout di 1000 ms è scaduto e il metodo resolve viene chiamato con "Done!".

La funzione nella parte then viene eseguita solo dopo che il metodo resolve viene chiamato.

.then può anche accettare un secondo argomento — un gestore di rifiuto — ma usare un .catch separato (come descritto di seguito) è più chiaro e cattura anche gli errori dai gestori precedenti.

Il metodo .catch

Il metodo .catch viene usato per gestire la promise se viene rigettata. Ciò significa che nel blocco della funzione promise viene generato un errore oppure viene chiamato il metodo reject.


javascript— editable

Per pattern di gestione degli errori più avanzati — rifiuto vs. errori generati, rilancio e recupero all'interno di una catena — vedere Gestione degli Errori con le Promise.

Il metodo .finally

Il metodo .finally consente di eseguire codice dopo che la promise è settled, indipendentemente dal suo esito. Non riceve argomenti (non sa se la promise è stata fulfilled o rejected) e passa il risultato o l'errore attraverso senza modifiche, rendendolo ideale per operazioni di pulizia come nascondere un indicatore di caricamento.


javascript— editable

Quando Vengono Eseguiti i Callback delle Promise? (Microtask)

Una sorpresa comune è che i callback .then, .catch e .finally non vengono mai eseguiti in modo sincrono, anche se la promise è già settled. Vengono schedulati nella coda delle microtask, che il motore elabora solo dopo che il codice sincrono corrente è terminato.

Ciò significa che il codice sincrono viene sempre eseguito per primo, e i callback delle promise vengono eseguiti prima dei timer (setTimeout), che si trovano nella coda separata delle macrotask.


javascript— editable

Anche se la promise viene risolta immediatamente e il timeout è 0, il callback della promise (3) viene eseguito prima del callback del timeout (4), perché la coda delle microtask viene completamente svuotata prima che venga eseguita la macrotask successiva.

Recuperare Dati da un API usando le Promise

Questo esempio mostra come recuperare dati da un API remota usando le promise.


javascript— editable

Concatenare le Promise

Il chaining delle promise è una funzionalità potente che consente di collegare più operazioni asincrone. Ogni .then restituisce una nuova promise, e qualsiasi valore che si return da un gestore diventa il valore di fulfillment di quella nuova promise — ecco perché l'esempio seguente porta un valore attraverso diversi passaggi. Per maggiori informazioni, consultare JavaScript: Promise e Chaining.


javascript— editable

Integrare async/await con le Promise JavaScript

Usare async/await in modo efficace può semplificare la gestione delle operazioni asincrone, rendendo il codice più pulito e facile da comprendere, mantenendo al contempo tutta la potenza delle promise JavaScript. Imparerai di più a riguardo in JavaScript async/await, ma ecco un semplice esempio.


javascript— editable

Conclusione

Padroneggiare le promise JavaScript è fondamentale per qualsiasi sviluppatore che voglia gestire le operazioni asincrone in modo efficiente. Ricorda il modello di base: una promise è pending finché l'executor non chiama resolve o reject, dopodiché è settled per sempre; si legge il risultato con .then/.catch/.finally; e quei callback vengono sempre eseguiti come microtask, dopo il codice sincrono corrente.

Dove andare dopo

Esercitazione

Pratica
Cos'è una promise in JavaScript?
Cos'è una promise in JavaScript?
Was this page helpful?