I understand the workflow of cancelling an ongoing request with AbortSignal, which is to pass it to the options:
const res = await fetch('/endpoint', { signal });
const data = await res.json();
However, what happens if the signal is cancelled after the request itself has finished, but before the data has been parsed? Like this:
const res = await fetch('/endpoint', { signal });
// Cancel signal here
const data = await res.json();
My tests in Firefox, Chrome and Safari show that it will be properly cancelled and throw during that res.json()
, but is it the official behavior?
const log = (...text) => document.body.insertAdjacentHTML('beforeend', `${text.join(' ')}<br />`);
(async () => {
try {
const controller = new AbortController();
const signal = controller.signal;
const res = await fetch('https://swapi.dev/api/films/2/', { signal });
log('Request:', signal.aborted);
controller.abort();
log('Before:', signal.aborted);
const data = await res.json();
log('After:', signal.aborted);
} catch (error) {
log('Cancelled:', error.name);
}
})();
// Request: false
// Before: true
// Cancelled: AbortError
From the output we can see it properly throws on res.json()
, it never reaches the After
step, and it's thrown with an AbortError
.
CodePudding user response:
Yes, that's the official behavior. json()
(and friends) consume the response's body. And as per step 10 of https://fetch.spec.whatwg.org/#dom-global-fetch that body can end up in an aborted state due to a signal. In that case, json()
(and friends) will essentially rethrow.