在开发 web 应用程序时,性能是一个重要的话题。为了提高用户体验和节省网络资源,我们需要对一些频繁或重复的 API 请求进行缓存,以减少不必要的服务器交互。缓存的原理是将第一次请求的数据保存在客户端,之后再次请求时直接从缓存中获取,而不是向服务器发送请求。
缓存的方式有很多种,根据不同的业务场景和需求,我们可以选择合适的方案来实现缓存功能。本文将介绍前端 API 请求缓存的三种方案,从简单到复杂,分别是:
一、数据缓存
- 数据缓存是最简单的一种缓存方案,它的思路是将第一次请求的数据保存在一个 Map 对象中,以 API 的名称或参数作为键,以数据作为值。之后再次请求时,先从 Map 对象中查找是否有对应的数据,如果有则直接返回,如果没有则向服务器发送请求,并将返回的数据保存在 Map 对象中。
- 数据缓存的优点是实现简单,适用于一些不需要更新的静态数据。缺点是无法处理同时多次请求的情况,也无法设置缓存的有效期,可能会导致数据过时或冗余。
示例代码如下:
// 创建一个 Map 对象用于存储数据
const dataCache = new Map();
// 定义一个获取商品列表的 API
async function getWares() {
// 以 API 的名称作为键
let key = "wares";
// 从 Map 对象中获取数据
let data = dataCache.getkey;
if (!data) {
// 如果没有数据,向服务器发送请求
const res = await request.get("/getWares");
// 对返回的数据进行一些处理
data = res.data;
// 将数据保存在 Map 对象中
dataCache.set(key, data);
}
// 返回数据
return data;
}
调用方式如下:
// 第一次调用,向服务器发送请求,获取数据
getWares().then((data) => {
console.log(data);
});
// 第二次调用,从 Map 对象中获取数据,不再发送请求
getWares().then((data) => {
console.log(data);
});
二、Promise 缓存
- Promise 缓存是对数据缓存的改进,它的思路是将第一次请求的 Promise 对象保存在一个 Map 对象中,以 API 的名称或参数作为键,以 Promise 对象作为值。之后再次请求时,先从 Map 对象中查找是否有对应的 Promise 对象,如果有则直接返回,如果没有则向服务器发送请求,并将返回的 Promise 对象保存在 Map 对象中。
- Promise 缓存的优点是可以处理同时多次请求的情况,避免重复发送请求,只有第一次请求会向服务器发送请求,之后的请求都会等待第一次请求的结果。缺点是无法设置缓存的有效期,可能会导致数据过时或冗余。
示例代码如下:
// 创建一个 Map 对象用于存储 Promise 对象
const promiseCache = new Map();
// 定义一个获取商品列表的 API
function getWares() {
// 以 API 的名称作为键
let key = "wares";
// 从 Map 对象中获取 Promise 对象
let promise = promiseCache.getkey;
// 如果没有 Promise 对象
if (!promise) {
// 向服务器发送请求,并返回一个 Promise 对象
promise = request.get("/getWares").then((res) => {
// 对返回的数据进行一些处理
return res.data;
}).catch((error) => {
// 如果请求出错,从 Map 对象中删除 Promise 对象,避免缓存错误的结果
promiseCache.deletekey;
// 抛出错误
return Promise.reject(error);
});
// 将 Promise 对象保存在 Map 对象中
promiseCache.set(key, promise);
}
// 返回 Promise 对象
return promise;
}
调用方式如下:
// 第一次调用,向服务器发送请求,获取数据
getWares().then((data) => {
console.log(data);
});
// 第二次调用,从 Map 对象中获取 Promise 对象,不再发送请求,等待第一次请求的结果
getWares().then((data) => {
console.log(data);
});
三、多 Promise 缓存
- 多 Promise 缓存是对 Promise 缓存的扩展,它的思路是将多个 API 请求的 Promise 对象保存在一个 Map 对象中,以 API 的名称或参数作为键,以 Promise 对象作为值。之后再次请求时,先从 Map 对象中查找是否有对应的 Promise 对象,如果有则直接返回,如果没有则向服务器发送请求,并将返回的 Promise 对象保存在 Map 对象中。最后,使用 Promise.all 方法将多个 Promise 对象合并为一个 Promise 对象,统一返回结果。
- 多 Promise 缓存的优点是可以同时获取多个 API 请求的数据,提高效率,只有第一次请求会向服务器发送请求,之后的请求都会等待第一次请求的结果。缺点是无法设置缓存的有效期,可能会导致数据过时或冗余。另外,如果其中一个 API 请求出错,会导致整个 Promise 对象被拒绝,无法获取其他 API 请求的数据。
示例代码如下:
// 定义一个对象,存储 API 的名称和对应的请求地址
const querys = {
wares: "/getWares",
skus: "/getSku",
};
// 创建一个 Map 对象用于存储 Promise 对象
const promiseCache = new Map();
// 定义一个函数,用于同时获取多个 API 请求的数据
async function queryAll(queryApiName) {
// 判断传入的参数是否是数组
const queryIsArray = Array.isArray(queryApiName);
// 统一处理参数,无论是字符串还是数组,都视为数组
const apis = queryIsArray ? queryApiName : [queryApiName];
// 创建一个数组,用于存储所有的 Promise 对象
const promiseApi = [];
// 遍历参数数组,对每个 API 进行处理
apis.forEach((api) => {
// 从 Map 对象中获取 Promise 对象
let promise = promiseCache.get(api);
// 如果没有 Promise 对象
if (!promise) {
// 向服务器发送请求,并返回一个 Promise 对象
promise = request.get(querys[api]).then((res) => {
// 对返回的数据进行一些处理
return res.data;
}).catch((error) => {
// 如果请求出错,从 Map 对象中删除 Promise 对象,避免缓存错误的结果
promiseCache.delete(api);
// 抛出错误
return Promise.reject(error);
});
// 将 Promise 对象保存在 Map 对象中
promiseCache.set(api, promise);
}
// 将 Promise 对象添加到数组中
promiseApi.push(promise);
});
// 使用 Promise.all 方法将多个 Promise 对象合并为一个 Promise 对象
return Promise.all(promiseApi).then((res) => {
// 根据传入的参数是字符串还是数组来返回数据,因为本身都是数组操作
// 如果传入的是字符串,则需要取出第一个元素
return queryIsArray ? res : res[0];
});
}
调用方式如下:
// 第一次调用,向服务器发送请求,获取数据
queryAll("wares").then((data) => {
console.log(data);
});
// 第二次调用,从 Map 对象中获取 Promise 对象,不再发送请求,等待第一次请求的结果
queryAll(["wares", "skus"]).then((data) => {
console.log(data);
});
总结
通过实施API请求缓存,我们可以显著提高前端应用程序的性能和用户体验。选择合适的缓存方案取决于应用程序的需求和特点。在实际开发中,我们可以根据数据的变化频率、数据的重要性、存储空间的限制等因素来选择适当的方案。结合合适的缓存方案,我们可以有效地减少网络请求,提高应用程序的响应速度,并降低服务器负载。同时,需要注意缓存的更新策略,以确保数据的准确性和实时性。
如果你对前端工程师职业和编程技术感兴趣,不妨访问编程狮官网(https://www.w3cschool.cn/)。编程狮官网提供了大量的技术文章、编程教程和资源,涵盖了前端工程师、编程、职业规划等多个领域的知识。无论你是初学者还是有经验的开发者,编程狮官网都为你提供了有用的信息和资源,助你在编程领域取得成功。不要错过这个宝贵的学习机会!