W3docs

Fetch: abort

Impara ad annullare le richieste fetch in JavaScript con AbortController e AbortSignal: abort attivati dall'utente, timeout, annullamento multiplo e gestione corretta di AbortError.

Una volta che una richiesta fetch() è in corso, continua a essere eseguita finché il server non risponde — anche se l'utente ha navigato altrove, digitato un nuovo termine di ricerca o il risultato non è più necessario. Queste richieste sprecate occupano connessioni, consumano batteria e banda, e possono consegnare risultati obsoleti che sovrascrivono quelli più recenti. L'interfaccia AbortController offre un modo pulito e standard per annullare una richiesta su richiesta.

Questo capitolo mostra come collegare AbortController, reagire alle azioni dell'utente, costruire timeout, annullare più richieste contemporaneamente e gestire correttamente l'AbortError risultante. Per saperne di più su fetch stesso, consulta la pagina precedente, Fetch API.

Come funziona AbortController

AbortController è un piccolo oggetto con un solo compito: possiede un AbortSignal e può portare quel segnale allo stato abortito. Il segnale è la parte che passi a fetch() (e a molte altre API del browser, come addEventListener). Quando chiami controller.abort(), ogni operazione che ha ricevuto quel segnale viene annullata.

Il pattern prevede sempre tre passaggi:

  1. Crea un controller: const controller = new AbortController().
  2. Passa controller.signal a fetch() nell'oggetto opzioni.
  3. Chiama controller.abort() ogni volta che vuoi annullare.

Quando un fetch viene annullato, la sua promise rigetta con un DOMException il cui name è "AbortError". Ecco perché ogni esempio qui sotto controlla error.name === 'AbortError' — in modo da poter ignorare la cancellazione intenzionale, pur visualizzando i veri errori di rete.

Utilizzo di base di AbortController

Ecco il più piccolo esempio completo. Si annulla immediatamente per mostrare il percorso di rifiuto:

javascript— editable

Creiamo un AbortController, passiamo il suo signal a fetch() e chiamiamo immediatamente controller.abort(). Poiché la richiesta non viene mai completata normalmente, viene eseguito il .catch() che segnala l'interruzione.

Ispezione del segnale: aborted e l'evento abort

Il segnale espone il suo stato in modo che altri elementi del codice possano reagire a una cancellazione. Due membri sono i più importanti:

  • signal.aborted — un boolean che diventa true una volta annullato.
  • l'evento "abort" — attivato sul segnale nel momento in cui viene chiamato abort().
javascript— editable

Questo è utile quando hai del lavoro non-fetch (un timer, un'animazione, un lettore di stream) che dovrebbe fermarsi nel momento in cui la richiesta viene annullata.

Un controller, un utilizzo. Un controller non può essere resettato. Una volta chiamato abort(), quel segnale rimane annullato per sempre, e qualsiasi nuovo fetch() avviato con esso viene rigettato istantaneamente. Per una nuova richiesta, crea un nuovo AbortController.

Esempio pratico: annullamento su un'azione dell'utente

Il motivo più comune per annullare è che l'utente cambia idea — facendo clic su "Annulla", chiudendo un dialogo o digitando una nuova query prima che la precedente fosse completata. Qui un pulsante annulla una richiesta in corso:

<body>
  <button id="abortButton">Abort Fetch Request</button>
  <script>
    const controller = new AbortController();
    const signal = controller.signal;
    document.getElementById('abortButton').addEventListener('click', () => {
      controller.abort();
    });
    fetch('https://httpbin.org/delay/5', { signal })
      .then(response => response.json())
      .then(data => alert(
        'Data is successfully fetched! Refresh the page and try aborting.'
      ))
      .catch(error => {
        if (error.name === 'AbortError') {
          alert('Fetch request was aborted by the user');
        } else {
          alert('Fetch error: ' + error.message);
        }
      });
  </script>
</body>

Fare clic sul pulsante con l'ID abortButton annulla la richiesta fetch in corso. L'endpoint https://httpbin.org/delay/5 impiega deliberatamente 5 secondi, quindi se si fa clic entro quell'intervallo, la richiesta viene rigettata con AbortError.

Annullamento di più richieste contemporaneamente

Un singolo segnale può essere passato a molte richieste. Una chiamata a controller.abort() le annulla tutte — utile quando una pagina abbandona una vista che aveva avviato diversi carichi paralleli:

javascript— editable

Poiché tutte e tre le richieste condividono un unico segnale, controller.abort() le annulla con una singola chiamata e Promise.all rigetta con AbortError. Per saperne di più sull'esecuzione di richieste in parallelo, consulta Promise API.

Annullamento dopo un timeout

Un uso molto comune di AbortController è quello di assegnare una scadenza a una richiesta: se il server è troppo lento, annulla e mostra un errore invece di aspettare all'infinito.

Il metodo manuale con setTimeout

Puoi abbinare il controller a un timer e combinarlo con qualsiasi altra logica asincrona. Qui un'operazione separata attiva l'annullamento dopo un secondo, mentre l'endpoint impiegherebbe cinque:

javascript— editable

Il fetch viene annullato dal timer dopo un secondo, ben prima che l'endpoint da cinque secondi possa rispondere. Leggi di più sui timer in async/await.

La scorciatoia: AbortSignal.timeout()

I browser moderni (e Node 17.3+) includono un helper integrato che crea un segnale che si annulla da solo dopo un dato numero di millisecondi — senza bisogno di controller o setTimeout:

javascript— editable

Nota che un abort per timeout rigetta con un TimeoutError, non con un AbortError, così puoi distinguere "ha impiegato troppo tempo" da "l'utente ha annullato". Se hai bisogno sia di un timeout sia di un pulsante di annullamento manuale, combina i segnali con AbortSignal.any([userSignal, AbortSignal.timeout(2000)]).

Gestione corretta di AbortError

Ogni volta che si annulla un fetch, la promise rigetta. Dimenticarsi di gestirlo produce un fastidioso "uncaught promise rejection" nella console, anche se la cancellazione era intenzionale. Due regole mantengono le cose pulite:

  • Avere sempre un .catch() (o try/catch con await) su un fetch annullabile.
  • Al suo interno, controlla error.name e tratta 'AbortError' / 'TimeoutError' come previsto — logga o mostra solo gli altri errori. Consulta Gestione degli errori con le promise per il pattern più generale.

Conclusione

AbortController è il modo standard per annullare le richieste fetch() in JavaScript. Crea un controller, passa il suo signal a una o più richieste e chiama abort() ogni volta che il lavoro non è più necessario. Hai visto la cancellazione attivata dall'utente, i timeout manuali e integrati, l'annullamento di più richieste contemporaneamente e come gestire l'AbortError risultante. Adottare questi pattern mantiene le tue app reattive e impedisce loro di sprecare tempo su risultati che nessuno sta più aspettando.

Pratica

Pratica
Qual è lo scopo di passare la proprietà signal di un AbortController a una richiesta fetch?
Qual è lo scopo di passare la proprietà signal di un AbortController a una richiesta fetch?
Was this page helpful?