Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

AbortController aborting ahead of time

What I want to achieve is to abort previous request after user had changed filters.
I have tried this:

const API_URL = "https://www.example.com"

const controller = new AbortController();
const signal = controller.signal;

export const fetchData = async (filters) => {
    // this console.log is fired only once
    console.log("Below I thought it would abort a request if ongoing, and ignore otherwise");
    controller.abort();
    const response = await fetch(`${API_URL}/products?${filters}`, { method: "GET", signal });
    return await response.json();
}

But what happens is my request being aborted even on first invoke, kind of ahead of time.
Other thing I tried is managing AbortController like so:

let controller;
let signal;

export const fetchData = async (filters) => {
    if (controller) {
        console.log("aborting")
        controller.abort();
        controller = null;
        fetchData(filters); // won't work until I invoke this function here recursively
        // and I expected something like 
        // controller = new AbortController();
        // signal = controller.signal;
        // ... then the rest of the function would work
    } else {
        controller = new AbortController();
        signal = controller.signal;
    }
    const response = await fetch(`${API_URL}/products?${filters}`, { method: "GET", signal });
    console.log("fetch fulfilled")
    return await response.json();
}

But the above approach wouldn’t work if I don’t include recursive call of fetchData because calling controller.abort() caused the whole function to throw error and not perform until the end, after the if block.
And this would leave me happy if it worked, but "fetch fulfilled" is logged out twice. Why?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

When there’s already a controller, you’re both calling fetchData (in the if branch) and doing the fetch later; that branch doesn’t terminate the function. So you end up with two fetches and two "fulfilled" messages.

Simplifying the code should sort it out (see *** comments):

let controller; // Starts out with `undefined`

export const fetchData = async (filters) => {
    // Abort any previous request
    controller?.abort(); // *** Note the optional chaining
    controller = new AbortController(); // *** Controller for this request
    const response = await fetch(`${API_URL}/products?${filters}`, {
        method: "GET",
        signal: controller.signal, // *** Using this controller's signal
    });
    console.log("fetch fulfilled");
    // *** Note: You need a check `response.ok` here
    if (!response.ok) {
        throw new Error(`HTTP error ${response.status}`);
    }
    return await response.json();
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading