如何将AbortController与Axios和React集成?

bbr*_*nck 16 cancellation cancellationtokensource reactjs react-native axios

Abortcontroller 信号不适用于 React 中的 Axios。

我想用 AbortController 替换 CancelToken (因为它已被弃用),但它不起作用,分别是请求没有被取消。

  let testController: AbortController;

  function loadTest() {
    testController = new AbortController();

    TestAPI.getTest(testController.signal)
      .then((e) => {
        console.log(e.data);
      })
      .catch((e) => {
        console.error(e);
      });
  }
Run Code Online (Sandbox Code Playgroud)

同样在 UseEffect Cleanup 中,我执行了此操作(这里应该取消),并且信号的状态也设置为中止,但请求仍然没有取消:

  useEffect(() => () => {
    if (testController) testController.abort();
    // console.log(testController.signal.aborted) => **true**
  }, []);
Run Code Online (Sandbox Code Playgroud)

这是我的 API,我将 AbortSignal 传递给请求:

  getTest(signal?: AbortSignal): Promise<AxiosResponse<Test[]>> {
    return axios.get(`${URI}/test`, { signal });
  },
Run Code Online (Sandbox Code Playgroud)

使用 Axios.CancelToken.source 时工作正常,但现在使用 AbortController,请求永远不会被取消。

使用:“axios”:“^ 0.26.0 ”,

有人设法将 AbortController 与 React 和 Axios 集成吗?或者 AbortController适用于 fetch 吗?

Dre*_*ese 28

axios.CancelToken据我所知,该API 并未被弃用,它仍在规范中,但根据文档 axios 还AbortController支持fetch API.

消除

Axios 支持 AbortController 以 fetch API 方式中止请求:

const controller = new AbortController();

axios.get('/foo/bar', {
   signal: controller.signal
}).then(function(response) {
   //...
});
// cancel the request
controller.abort()
Run Code Online (Sandbox Code Playgroud)

目前尚不清楚具体在哪里testController声明:

let testController: AbortController;
Run Code Online (Sandbox Code Playgroud)

但我怀疑它位于函数组件的主体中,并在后续渲染周期中重新声明。

我建议使用 React ref 来存储AbortController,并在您的应用程序中引用此 ref 值。这样,组件在渲染周期之间保持控制器的稳定引用,以便在useEffect组件卸载时在任何钩子清理函数中引用以取消正在进行的请求。

const abortControllerRef = useRef<AbortController>(new AbortController());

function loadTest() {
  TestAPI.getTest(abortControllerRef.current.signal)
    .then((e) => {
      console.log(e.data);
    })
    .catch((e) => {
      console.error(e);
    });
}

useEffect(() => {
  const controller = abortControllerRef.current;
  return () => {
    controller.abort();
  };
}, []);
Run Code Online (Sandbox Code Playgroud)


Ale*_*ert 8

我建议阅读这篇文章

简而言之,您想使用它useEffect来创建控制器,更重要的是,使用return语句来中止控制器。

useEffect(() => {
 const controller = new AbortController();
 const signal = controller.signal;
 getData(signal)

 //cleanup function
 return () => {controller.abort();};
}, [fetchClick]);
Run Code Online (Sandbox Code Playgroud)

getData然后您可以以axios以下形式调用函数:

const getData = async (signal) =>{
 const res = await axios.get(url, {signal: signal}).then(...)
}
Run Code Online (Sandbox Code Playgroud)