简体   繁体   中英

AbortController.abort(reason), but the reason gets lost before it arrives to the fetch catch clause

I am implementing abortable fetch calls .

There are basically two reasons for aborting the fetch on my page:

  • the user decides he/she does not want to wait for the AJAX data anymore and clicks a button; in this case the UI shows a message "call /whatever interrupted"
  • the user has moved to another part of the page and the data being fetched are no longer needed; in this case I don't want the UI to show anything, as it'd just confuse the user

In order to discriminate the two cases I was planning to use the reason parameter of the AbortController.abort method, but the .catch clause in my fetch call always receives a DOMException('The user aborted a request', ABORT_ERROR) .

I have tried to provide a different DOMException as reason for the abort in case 2, but the difference is lost.

Has anyone found how to send information to the fetch .catch clause with regards to the reason to abort?

In the example below, I demonstrate how to determine the reason for an abortion of a fetch request. I provide inline comments for explanation. Feel free to comment if anything is unclear.

Re-run the code snippet to see a (potentially different) random result

 'use strict'; function delay (ms, value) { return new Promise(res => setTimeout(() => res(value), ms)); } function getRandomInt (min = 0, max = 1) { return Math.floor(Math.random() * (max - min + 1)) + min; } // Forward the AbortSignal to fetch: // https://docs.github.com/en/rest/repos/repos#list-public-repositories function fetchPublicGHRepos (signal) { const headers = new Headers([['accept', 'application/vnd.github+json']]); return fetch('https://api.github.com/repositories', {headers, signal}); } function example () { const ac = new AbortController(); const {signal} = ac; const abortWithReason = (reason) => delay(getRandomInt(1, 5)) .then(() => { console.log(`Aborting ${signal.aborted ? 'again ' : ''}(reason: ${reason})`); ac.abort(reason); }); // Unless GitHub invests HEAVILY into our internet infrastructure, // one of these promises will resolve before the fetch request abortWithReason('Reason A'); abortWithReason('Reason B'); fetchPublicGHRepos(signal) .then(res => console.log(`Fetch succeeded with status: ${res.status}`)) .catch(ex => { // This is how you can determine if the exception was due to abortion if (signal.aborted) { // This is set by the promise which resolved first // and caused the fetch to abort const {reason} = signal; // Use it to guide your logic... console.log(`Fetch aborted with reason: ${reason}`); } else console.log(`Fetch failed with exception: ${ex}`); }); delay(10).then(() => console.log(`Signal reason: ${signal.reason}`)); } example();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM