面试题答案
一键面试避免不必要重复请求策略
- 使用请求队列:在高阶组件中维护一个请求队列,当有相同请求发起时,先检查队列中是否已有该请求。如果有,则不再发起新请求,而是等待已有请求完成后共享结果。
- 基于参数去重:如果API请求的参数不同,可根据参数组合来判断是否为重复请求。
处理请求缓存策略
- 内存缓存:在高阶组件内部维护一个缓存对象,以请求的标识(例如URL和参数)作为键,请求结果作为值。每次发起请求前先检查缓存中是否有对应结果。
- 持久化缓存:对于一些不经常变化的数据,可以使用本地存储(如
localStorage
)或IndexedDB进行持久化缓存,在页面刷新或重新加载时仍可使用缓存数据。
代码示例
import React from 'react';
import { useState, useEffect } from'react';
// 模拟API请求函数
const apiRequest = (url, params) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ data: `Response from ${url} with params ${JSON.stringify(params)}` });
}, 1000);
});
};
// 高阶组件
const withAPICall = (url, params) => {
return (WrappedComponent) => {
return (props) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
// 内存缓存对象
const cache = {};
// 请求队列
const requestQueue = {};
const fetchData = async () => {
const requestKey = `${url}-${JSON.stringify(params)}`;
if (cache[requestKey]) {
setData(cache[requestKey]);
return;
}
if (requestQueue[requestKey]) {
const existingPromise = requestQueue[requestKey];
const existingData = await existingPromise;
setData(existingData);
return;
}
setLoading(true);
try {
const response = await apiRequest(url, params);
setData(response.data);
cache[requestKey] = response.data;
} catch (err) {
setError(err);
} finally {
setLoading(false);
delete requestQueue[requestKey];
}
};
useEffect(() => {
fetchData();
}, []);
return (
<WrappedComponent
data={data}
loading={loading}
error={error}
{...props}
/>
);
};
};
};
// 使用高阶组件的组件
const MyComponent = ({ data, loading, error }) => {
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{data && <p>{data}</p>}</div>;
};
const EnhancedComponent = withAPICall('/api/data', { key: 'value' })(MyComponent);
export default function App() {
return (
<div>
<EnhancedComponent />
</div>
);
}
在上述代码中:
- 避免重复请求:通过
requestQueue
对象实现。当有相同请求时,新请求等待已有请求完成并共享结果。 - 处理请求缓存:通过
cache
对象实现内存缓存。每次请求前先检查缓存,若有则直接使用缓存数据。