使用 JavaScript 缓存 API 请求
使用 API 是 JavaScript 的日常工作,但这也有其局限性,每秒的请求数是最常见的。在这种情况下,我们将实现一个基于时间缓存数据的算法。假设我们确定要获取的数据在一定时间段内不会发生变化,那么我们可以将数据缓存在该时间段内。有些数据可以按秒、分钟甚至天进行缓存。
在这个例子中,我们将使用来自Open Weather API的数据,这是一个用于获取不同城市天气的 API,对于天气,我们可以说它不会每 10 分钟改变一次,因此我们可以缓存这段时间的数据。
让我们准备简单的模板来输入城市并显示模糊数据。
<!DOCTYPE html>
<html>
<head>
<title>Cache</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app">
<h1>Hello Cache!</h1>
<div>
<input type="text" id="inputWeather" placeholder="Fetch weather for" />
</div>
<div id="container"></div>
</div>
<script src="src/index.js"></script>
</body>
</html>
我们的缓存结构应该存储我们想要缓存的元数据以及数据被缓存前的时间戳。为了方便获取/设置,该结构将采用 HashMap 形式。键可以是小写的城市名称(如果键可以重复,可以使用更复杂的键)。
const cache = {
london: {
...metadata,
cacheTimer: 1234567890
},
...
}
我们获取数据的常规函数如下:
async function fetchWeatherInfo(cityName) {
let weatherInfo = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${cityName}&APPID=${api}`
)
.then(data => data.json())
.then(myJson => myJson)
return weatherInfo
}
我们接收城市名称并进行获取,返回元数据。此函数将被缓存函数包装,在缓存函数中,我们还会接收 cityName 以及缓存生效的时间。如果哈希键不存在或时间小于现在,我们将获取新数据并缓存。该函数将如下所示:
const cache = {}
let cacheTimer = 0
async function fetchWithCache(cityName, time) {
const now = new Date().getTime()
if (!cache[cityName] || cache[cityName].cacheTimer < now) {
cache[cityName] = await fetchWeatherInfo(cityName)
cache[cityName].cacheTimer = getCacheTimer(time)
}
return cache[cityName]
}
在函数内部,fetchWithCache
我们获取缓存计时器,该计时器等于当前日期 + 我们希望数据被缓存的时间。让我们创建获取缓存计时器的函数:
function getCacheTimer(time) {
const now = new Date().getTime()
if (cacheTimer < now + time) {
cacheTimer = now + time
}
return cacheTimer
}
此时,我们已经有了用于正常获取数据的函数、用于设置缓存数据的计时器的函数以及用于缓存数据的函数。接下来,让我们创建一个在 HTML 中显示天气数据的函数。为了在 HTML 中显示数据,我们需要获取输入元素并设置一个事件监听器来监听变化。cacheTime 是我们希望数据持久化的时长,在本例中为 100,000 毫秒。在事件监听器中,我们调用 displayWeatherData 函数,该函数将调用我们的缓存函数,并从缓存或 API 请求中获取数据。
const input = document.getElementById("inputWeather")
const weatherContainer = document.getElementById("container")
const cacheTime = 100000
function init() {
input.addEventListener("change", updateValue)
function updateValue(e) {
displayWeatherData(e.target.value)
}
}
async function displayWeatherData(cityName) {
const weatherInfo = await fetchWithCache(cityName.toLowerCase(), cacheTime)
if (!weatherInfo || !weatherInfo.weather) {
weatherContainer.innerHTML = `There's an error with request.`
return
}
weatherContainer.innerHTML = `<p>${weatherInfo.name}</p><p>${weatherInfo.weather[0].main}<p><p>${weatherInfo.main.temp}</p><p>--------------</p>`
console.log(cache)
}
init()
为了调试目的,我留下了以下console.log
声明:您可以检查浏览器 DevTools 中的“网络”选项卡,并确认该请求仅在第一次执行,然后缓存 10 秒。
您可以在这里看到它的实际效果:https://codesandbox.io/s/kind-dew-5bbrn
感谢阅读!
鏂囩珷鏉ユ簮锛�https://dev.to/adancarrasco/caching-api-requests-in-javascript-mc4