如何封装一个请求,让其多次调用的时候,实际只发起一个请求的时候,返回同一份结果?
封装一个请求使其在多次调用时只发起一次请求,并返回相同结果,通常是通过请求去重(debouncing)来实现的。这种功能对于避免重复的网络请求、提高性能和减少不必要的负载非常有用。
同时,我们需要确保在请求完成之前,对相同请求的重复调用都会共享相同的请求 Promise。避免出现连续发出相同的请求,在第一个请求尚未完成时,那么可能会发出多个请求的情况。
可以通过以下步骤来实现这个功能:
1. 使用一个缓存机制
我们可以使用 JavaScript 对象或 Map 来缓存已经发起的请求,并在 subsequent 请求中返回缓存的结果。缓存的关键是确保相同的请求参数对应同一个缓存条目。
2. 创建请求缓存封装
以下是一个基于 axios 的请求去重的封装示例:
javascript
import axios from 'axios';
// 请求缓存
const requestCache = new Map();
async function fetchData(url, params) {
// 生成缓存 key
const cacheKey = `${url}?${new URLSearchParams(params).toString()}`;
// 检查缓存中是否已有数据
if (requestCache.has(cacheKey)) {
return requestCache.get(cacheKey);
}
// 创建请求 Promise
const requestPromise = axios.get(url, { params })
.then(response => {
// 请求成功,存储结果
requestCache.delete(cacheKey); // 请求完成后,移除缓存
return response.data;
})
.catch(error => {
// 请求失败,清除缓存
requestCache.delete(cacheKey);
throw error;
});
// 存储请求 Promise
requestCache.set(cacheKey, requestPromise);
// 返回 Promise
return requestPromise;
}
export default fetchData;注意事项:
缓存请求 Promise:每个请求的 Promise 被缓存到 requestCache 中。后续的相同请求会返回这个缓存的 Promise。
请求完成后移除缓存:请求成功或失败后,删除缓存,以防止缓存中的 Promise 长时间存在,避免内存泄漏。
请求失败处理:如果请求失败,清理缓存并抛出错误,以便后续调用可以重新发起请求。
3. 使用请求缓存
使用封装好的 fetchData 函数来发起请求。多次调用相同的请求 URL 和参数只会发起一次网络请求,并返回相同的结果。
javascript
import fetchData from './fetchData';
// 使用示例
fetchData('https://api.example.com/data', { id: 1 })
.then(data => console.log(data))
.catch(error => console.error(error));
// 再次调用相同的请求
fetchData('https://api.example.com/data', { id: 1 })
.then(data => console.log(data)) // 共享相同的请求结果
.catch(error => console.error(error));题目要点:
- 单一请求:确保相同请求的多次调用返回相同的 Promise,避免发出多个网络请求。
- 缓存管理:请求完成后,删除缓存,避免长时间缓存未清理。
- 错误处理:处理请求失败情况,并清理缓存以便重新请求。