TIL: Abort Controller

ยท

2 min read

Usually Async requests are not cancellable and you just have to abandon those requests.

Today I learned about the Abort Controller and it is very useful.

It has a really good support in general and if you are using Babel with CoreJS, I thing it will be transpiled anyway.

Let's take a look at an example. Let's create a simple Image Uploader in plain HTML, CSS and JS.

HTML:

  <form id="imageUploadForm">
    <div>
      <label for="file">Image</label>
      <div>
        <input type="file" name="file" id="file" />
      </div>
    </div>
    <div>
      <button type="submit">Start Upload</button>
      <button type="reset">Reset</button>
      <button type="button" id="stop">Stop Upload</button>
    </div>
  </form>

And JavaScript:

document.addEventListener('DOMContentLoaded', () => {
  const formEl = document.querySelector('#imageUploadForm')
  formEl && attachFormEvents(formEl)
})

const attachFormEvents = (formEl) => {
  if (!formEl) {
    return
  }
  const stop = formEl.querySelector('#stop')
  const controller = new AbortController()
  const signal = controller.signal

  formEl.addEventListener('submit', (e) => {
    e.preventDefault()
    e.stopPropagation()
    const formData = new FormData(formEl)
    const url = 'https://1u3o3.sse.codesandbox.io/upload'
    return fetch(url, {signal, method: 'POST', body: formData})
      .then(r => r.json())
      .then(console.log)
      .catch(console.error)
  })

  stop && stop.addEventListener('click', (e) => {
    controller.abort()
  })
}

How it works? Lets take a look at it step by step:

  1. Create an Abort Controller with new AbortController()
  2. Get the signal from the Controller with controller.signal
  3. When creating fetch, provide abort signal in the Request Configuration with key signal
  4. Call controller.abort() whenever you wanna abort the request

Let me know if you have tried the Abort Controller already.