在 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()
}
GET
和 POST
调用被提取为
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
需要在离开页面时取消请求调用,或者当同一个 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()
}
GET
和 POST
调用被提取为
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