用JavaScript缓存API请求
TLDR;
消耗API是JavaScript中的日常工作,这也有其局限性,每秒的请求数量是最常见的,在这种情况下,我们将实现一种基于时间来缓存数据的算法。假设我们确定要获取的数据在一定时间内不会发生变化,那么我们可以缓存该跨度的数据。某些数据可以按秒,分钟甚至几天来缓存。
在此示例中,我们将使用来自开放天气API的数据,这是一个获取不同城市天气的API,对于天气,我们可以说它不会每10分钟更改一次,因此我们可以为此缓存数据一段的时间。
让我们准备一个简单的模板来输入城市并显示模糊数据。
快取
<元 字符集=“ UTF-8” />
id =“应用”>
你好缓存
<输入 类型=“文本” id =“ inputWeather” 占位符=“获取天气” />
id =“容器”>
我们的缓存结构应存储我们要缓存的元数据+时间戳,直到数据将被缓存为止,以使其更易于获取/设置,该结构将成为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 => (weatherInfo = 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中显示数据,我们需要获取input元素并为on更改设置事件监听器。 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 = `${weatherInfo.name}${weatherInfo.weather[0].main}${weatherInfo.main.temp}--------------
`
console.log(cache)
}
init()
出于调试目的,我离开了 console.log
语句,您可以在浏览器DevTools中检查“网络”选项卡,并确认仅在第一次执行请求,然后将其缓存10秒钟。
您可以在此处查看它的运行情况:https://codesandbox.io/s/kind-dew-5bbrn
谢谢阅读