<main>
<p>
<small>
  (If you're curious how this works, check out the requests in DevTools.)
</small>
</p>
<fieldset id="starter">
  <select id="delay">
    <option value="10000">10 sec</option>
    <option value="5000" selected="">5 sec</option>
    <option value="1000">1 sec</option>
  </select>
  <button id="doFetch">Do slow network fetch</button>
</fieldset>
<button id="abortFetch" disabled>Abort fetch</button>
<pre id="status" class=""></pre>
</main>

fieldset {
  display: inline-block;
  padding: 0;
  border: 0;
}
:host {
  color: inherit !important;
}
main {
  position: relative;
  padding: 12px;
  margin-bottom: 12px;
  padding-top: 6px;
}
main::before {
  content: '';
  inset: 0;
  border-radius: 4px;
  background: currentColor;
  opacity: 0.05;
  position: absolute;
  z-index: -100;
}
* {
  margin: 0;
}
#status.error {
  color: red;
}
const fetchButton = document.querySelector('#doFetch');
const abortButton = document.querySelector('#abortFetch');
const delaySelect = document.querySelector('#delay');
const statusText = document.querySelector('#status');
const delaymeURL = 'https://deelay.me';
const imageURL = 'https://i.imgur.com/fHyEMsl.jpg';

fetchButton.onclick = async () => {
  const delayValue = delaySelect.value;
  
  fetchButton.disabled = true;
  abortButton.disabled = false;
  statusText.classList.remove('error');
  statusText.innerText = `Doing slow network fetch over ${delayValue}ms...`;
  
  const controller = new AbortController();

  // wire up abort button
  abortButton.onclick = () => controller.abort();

  try {
    const r = await fetch(`${delaymeURL}/${delayValue}/${imageURL}`, { signal: controller.signal });
    statusText.innerText = 'Loaded image';
    // TODO: do something ๐Ÿคท
  } catch (e) {
    const isUserAbort = (e.name === 'AbortError');
    // TODO: show err ๐Ÿงจ
    if(isUserAbort) {
      statusText.innerText = 'Fetched failed due to: AbortError: The user aborted'
      statusText.classList.add('error');
    }
    // this will be a DOMException named AbortError if aborted ๐ŸŽ‰
  } finally {
     fetchButton.disabled = false;
     abortButton.disabled = true;
  }
};

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.