在 React 世界中获取调用:ReactJS

fetch calls in react world: ReactJS

需要在离开页面时取消请求调用,或者当同一个 api 调用被多次调用时(保持最后一个处于活动状态)。

这就是API被提取出来的方式(只是一个高层次)

AJAX.ts

export async function customAjax(options){
   let options = {};
   options.headers = { ...options.headers, ...obj.headers };
   const response = await fetch(url, options);
   await response.json()
}

GETPOST 调用被提取为

API.ts

const get = (url, extra = {}) => request({ url, type: "GET", ...extra });
const post = (url, payload, extra = {}) => request({ url, data: payload ,type: "POST",
}, ...extra });

在 React 组件中,我按如下方式调用这些实用程序:

function MyComponent(){
  useEffect(() => {
    makeCall();
  }, []);

 async function makeCall(){
   const { response, error } = await API.post(URL, payload);
   // Handling code is not added here
   // In the similar fashion GET calls are also made
 }
}

我遇到过 Abortcontroller 取消请求,我们可以在卸载组件期间使用 abort 方法。

有没有办法在实用级别执行此操作,可能在 customAjax 内,这样我就可以避免在任何地方编写中止控制器代码?

据我了解...您所描述的与内存泄漏问题没有什么不同。目前避免内存泄漏的方法是 AbortController().

至于在“实用程序级别”处理这个问题,我认为这是不可行的,而且确实会违背 api 不知道 React 发生了什么的首选概念组件级别;即关注点分离..

因此,为了满足您的要求,您需要使用 AbortController(),或使用反映组件是否已安装的布尔标志的自定义实现,基于每个组件。

使用布尔标志,您可以在 api 中接受参数,将标志作为参数传递;但同样,我认为这将被视为 anti-pattern.

我知道您正在寻找一个最小的实现;但标准做法相当少:

useEffect(() => {
   let abortController = new AbortController();
    // Async code
   return () => { abortController.abort(); }
}, []);

使用布尔标志会更冗长,并且在您的情况下需要这样的事情:

useEffect(() => {
  let isMounted = true;
  
  customAjax(isMounted);

  return () => {
   isMounted = false;
  }
}, []);

要处理 out-of-order ajax 响应,您可以在效果内使用局部变量。例如,

useEffect(() => {
    let ignore = false;
    async function fetchProduct() {
      const response = await fetch('http://myapi/product/' + productId);
      const json = await response.json();
      if (!ignore) setProduct(json);
    }

    fetchProduct();
    return () => { ignore = true };
}, [productId]);

ignore 变量将确保只有最新请求的响应才会更新为状态。参考 - https://reactjs.org/docs/hooks-faq.html#performance-optimizations

关于内存泄漏问题,请参阅此讨论 - https://github.com/reactwg/react-18/discussions/82