Can’t make new fetch request after aborting previous

Tags: , ,



I need to change a parameters that defines what data should come from my requests, also this application needs to refresh every fixed interval of time. If the user changes the parameter of interest in the middle of a previous refresh request things start to behave strange and some unexpected behavior occurs.

So my approach was to abort all previous requests before starting the new ones, but after using await controller.abort() it seems that the next requests are never triggered, Do I need to clear the signal or something like that?

const controller = new AbortController();
const async fetchData = (url, body = null) => {
  let data;
  const signal = controller.signal;
  const headers = { ... };
  response = await fetch(url, body ? {
    method: "POST",
    body: JSON.stringify(body),
    signal,
    headers
  } : { headers, signal });;
  data = await response.json()
  return data
}

const firstData = await fetchData(url1, body1);
await controller.abort();
const secondData= await fetchData(url2, body2);

What happens is that secondData always is undefined, actually this second request never happens (looking on network traffic). If I stop source and try to run await fetchData(url2) after .abort() has executed it prompts an erros saying that Uncaught SyntaxError: await is only valid in async function or if I try to run it without await it returns a pending promise, but the actual request is nowhere to be seen in traffic tab.


Solved

Applying what was suggested on the ansewr I created wrapper on the function, to call new controllers everytime.

let controller = null;
let fetchData = null;
const initializeFetchData = () => {
  const controller = new AbortController();
  const async fetchData = (url, body = null) => {
    let data;
    const signal = controller.signal;
    const headers = { ... };
    response = await fetch(url, body ? {
      method: "POST",
      body: JSON.stringify(body),
      signal,
      headers
    } : { headers, signal });;
    data = await response.json()
    return data
  }
}

initializeFetchData();
const firstData = await fetchData(url1, body1);
controller.abort();
initializeFetchData();
const secondData= await fetchData(url2, body2);

Answer

You are using the sameAbortController for two different requests. After calling .abort() on theAbortController you have updated the state of it’s AbortSignal which then renders the second request void.

You should use a separate AbortController for each request if you want this behavior. Of course, it is perfectly acceptable to reuse an AbortController for multiple fetch requests if you want to be able to abort all of them in one go.

A couple of other points…

  • .abort() is a synchronous method which returns void so you do not need the await prefix when calling .abort().
  • In your code example, the first request will never be aborted as you are awaiting the fetch request, which will complete before the .abort() is called.


Source: stackoverflow