这个场景属于一种性能优化吧,面试中也可能会问到你。
话不多说直接上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h4>Fetch</h4>
<p>
如何实现一个缓存机制,使得在Web开发中,当多次发起相同的AJAX请求时,能够保证每次都能获取到数据,但实际上只发送一次请求到服务器,请用
JS 实现该方法
</p>
<div>
<button id="btn">点击发送</button>
</div>
<script>
const cache = {};
function fetchData(url) {
// 有缓存
if (cache[url]) {
//Promise.resolve() 是 JavaScript 内置的一个方法,用于创建一个立即被解析(fulfill)的 Promise 对象
// return Promise.resolve(cache[url]);
return cache[url];
} else {
// 没有缓存,发起 AJAX 请求
//fetch() 是一个 JavaScript 内置的 API,用于发送 HTTP 请求并获取响应。
return fetch(url)
.then((response) => {
// 将请求得到的数据存入缓存,
// response 它只是一个 HTTP 响应,而不是真的 JSON。
// json()这个方法会异步读取响应体,并且尝试将其解析为 JSON 格式。
if (response.ok) cache[url] = response.json();
return cache[url];
})
.catch((error) => {
console.error("Error fetching data:", error);
});
}
}
//addEventListener("click", () => {})这是给选定的元素添加事件监听器的方法
document.getElementById("btn").addEventListener("click", () => {
fetchData("https://api.realworld.io/api/tags").then((data) => {
console.log("Data:", data);
});
});
</script>
</body>
</html>
这个代码就是我在面试中回答的结果,但是后面面试官又问了另一个问题,
如果接口请求时间比较长,还没返回结果又调用了请求方法,怎么还是只发起一次请求,复用第一次请求的结果?
这个问题我当时想到的是用定时器,具体的操作方法我没有写,但是应该会有一些问题。
现在我推荐的是另一种方法,是直接返回第一次调用的promise,上代码!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h4>Fetch</h4>
<p>
如何实现一个缓存机制,使得在Web开发中,当多次发起相同的AJAX请求时,能够保证每次都能获取到数据,但实际上只发送一次请求到服务器,请用
JS 实现该方法
</p>
<div>
<button id="btn">点击发送</button>
</div>
<script>
const cache = {};
function fetchData(url) {
console.log(cache, cache[url], "cache");
// 有缓存且数据已经准备好
if (cache[url] && cache[url].data) {
return Promise.resolve(cache[url].data);
} else if (cache[url] && cache[url].promise) {
// 有缓存但数据还在请求中,返回之前的请求 promise
console.log(cache[url].promise, "cache[url].promise");
return cache[url].promise;
} else {
// 没有缓存,发起新的请求
const fetchPromise = fetch(url)
.then((response) => response.json())
.then((data) => {
// 将请求得到的数据存入缓存
cache[url].data = data;
return data;
})
.catch((error) => {
console.error("Error fetching data:", error);
});
// 将 promise 存入缓存
cache[url] = { promise: fetchPromise };
return fetchPromise;
}
}
//addEventListener("click", () => {})这是给选定的元素添加事件监听器的方法
document.getElementById("btn").addEventListener("click", () => {
fetchData("https://api.realworld.io/api/tags").then((data) => {
console.log("Data:", data);
});
});
</script>
</body>
</html>
将第一次请求的promise存储起来,在请求还没成功的时候,返回promise对象,相当于返回的就是第一次请求的内容结果