BEST_PRACTICES /
Aborting network requests

← Back

Overview

When making a network request, in JavaScript, that is instantiated by UI (for example a button), it is a good idea to keep track of prior requests, and cancel them if a new one gets instantiated. Cancelling any operations in the post-request flow is also important, so that the UI does not update in a staggered fashion.

With the AbortController constructor, we can abort previous calls, which the fetch function will observe, by using the AbortController's signal property. Calling abort() will cancel the request, but will also mean the fetch() call throws an error.

For more fine grained flow control, to determine if the fetch error is a genuine network error, or an aborted request, we can use signal.aborted - which will be true if AbortController#abort was called.

Example

Here is a basic example, using delegated-events to handle requests upon clicking .my-element:

let previousController: AbortController | null = null

on('click', '.my-element', () => {
  previousController?.abort()

  const {signal} = (previousController = new AbortController())
  try {
    const res = fetch(myUrl, {signal})

    // ... Add logic here with the completed network response

  } catch (e) {

    // ... Add logic here if you need to report failed network requests.
    // Do not rethrow for network errors!

  }

  if (signal.aborted) {
    // Here you can add logic for if the request was cancelled, but
    // usually what you want to do is just return early to avoid
    // cleaning up the loading UI (bear in mind if the request is
    // cancelled then another one will be in its place).
    return
  }

  // ... Add cleanup logic here, such as removing `loading` classes.

})