简体   繁体   English

AbortController 提前中止

[英]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:我尝试的另一件事是像这样管理AbortController

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.但是如果我不包含fetchData的递归调用,上述方法将不起作用,因为调用controller.abort()导致整个 function 在if块之后抛出错误并且直到最后才执行。
And this would leave me happy if it worked, but "fetch fulfilled" is logged out twice.如果它有效,这会让我很高兴,但是"fetch fulfilled"被注销了两次。 Why?为什么?

When there's already a controller, you're both calling fetchData (in the if branch) and doing the fetch later;当已经有 controller 时,您将同时调用fetchData (在if分支中)稍后进行 fetch; that branch doesn't terminate the function.该分支不会终止 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();
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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