如何从在 Node 中使用 fetch 的异步函数缓存数据
How to cache data from async function that uses fetch in Node
我想看看是否有办法缓存来自获取异步调用的 json 响应,可能使用 LRU。
我试过使用几个包,例如 node-cache 和 lru-cache,但我认为它们不起作用,因为我的函数是异步的。
我的 fetch 函数基本上是这样的:
const jsonFetch = async (url) => {
try {
const response = await fetch (url)
const json = await response.json();
return json
}
catch (error) {
console.log(error)
}
}
例如,如果我让某人在一分钟内走我的路线 20 次,我想轻松获取数据并 return 在 0.03 毫秒而不是 0.3 毫秒内做出响应。目前,它总是使用 URL 来获取数据。
异步函数不会阻止缓存结果。您正在查看的库可能无法处理这些承诺,但这里有一个基本的概念证明可能有助于开始工作:
let cache = {}
const jsonFetch = async (url) => {
if (url in cache) { // return cached result if available
console.log("cache hit")
return cache[url]
}
try {
const response = await fetch (url)
const json = response.json();
cache[url] = json // cache response keyed to url
return json
}
catch (error) {
console.log(error)
}
}
jsonFetch("https://jsonplaceholder.typicode.com/todos/1").then((user) => console.log(user.id))
// should be cached -- same url
setTimeout(() => jsonFetch("https://jsonplaceholder.typicode.com/todos/1").then((user) => console.log(user.id)), 2000)
// not in cache
setTimeout(() => jsonFetch("https://jsonplaceholder.typicode.com/todos/2").then((user) => console.log(user.id)), 2000)
您只会在第一个请求returnsreturns一个要缓存的值
之后发出的请求中获得缓存命中
这已经有一段时间了,但我同意@sleepy012 的评论。如果我想避免并行调用,技巧应该是缓存承诺,而不仅仅是值。所以这样的事情应该有效:
let cache = {}
function cacheAsync(loader) {
return async (url) => {
if (url in cache) { // return cached result if available
console.log("cache hit")
return cache[url]
}
try {
const responsePromise = loader(url)
cache[url] = responsePromise
return responsePromise
}
catch (error) {
console.log('Error', error.message)
}
};
}
function delayedLoader(url) {
console.log('Loading url: ' + url)
return new Promise((r) => setTimeout(r, 1000,'Returning ' + url));
}
const cachedLoader = cacheAsync(delayedLoader);
cachedLoader('url1').then((d) => console.log('First load got: ' + d));
cachedLoader('url1').then((d) => console.log('Second load got: ' + d));
cachedLoader('url2').then((d) => console.log('Third load got: ' + d));
cachedLoader('url2').then((d) => console.log('Fourth load got: ' + d));
console.log('Waiting for load to complete');
我想看看是否有办法缓存来自获取异步调用的 json 响应,可能使用 LRU。
我试过使用几个包,例如 node-cache 和 lru-cache,但我认为它们不起作用,因为我的函数是异步的。
我的 fetch 函数基本上是这样的:
const jsonFetch = async (url) => {
try {
const response = await fetch (url)
const json = await response.json();
return json
}
catch (error) {
console.log(error)
}
}
例如,如果我让某人在一分钟内走我的路线 20 次,我想轻松获取数据并 return 在 0.03 毫秒而不是 0.3 毫秒内做出响应。目前,它总是使用 URL 来获取数据。
异步函数不会阻止缓存结果。您正在查看的库可能无法处理这些承诺,但这里有一个基本的概念证明可能有助于开始工作:
let cache = {}
const jsonFetch = async (url) => {
if (url in cache) { // return cached result if available
console.log("cache hit")
return cache[url]
}
try {
const response = await fetch (url)
const json = response.json();
cache[url] = json // cache response keyed to url
return json
}
catch (error) {
console.log(error)
}
}
jsonFetch("https://jsonplaceholder.typicode.com/todos/1").then((user) => console.log(user.id))
// should be cached -- same url
setTimeout(() => jsonFetch("https://jsonplaceholder.typicode.com/todos/1").then((user) => console.log(user.id)), 2000)
// not in cache
setTimeout(() => jsonFetch("https://jsonplaceholder.typicode.com/todos/2").then((user) => console.log(user.id)), 2000)
您只会在第一个请求returnsreturns一个要缓存的值
之后发出的请求中获得缓存命中这已经有一段时间了,但我同意@sleepy012 的评论。如果我想避免并行调用,技巧应该是缓存承诺,而不仅仅是值。所以这样的事情应该有效:
let cache = {}
function cacheAsync(loader) {
return async (url) => {
if (url in cache) { // return cached result if available
console.log("cache hit")
return cache[url]
}
try {
const responsePromise = loader(url)
cache[url] = responsePromise
return responsePromise
}
catch (error) {
console.log('Error', error.message)
}
};
}
function delayedLoader(url) {
console.log('Loading url: ' + url)
return new Promise((r) => setTimeout(r, 1000,'Returning ' + url));
}
const cachedLoader = cacheAsync(delayedLoader);
cachedLoader('url1').then((d) => console.log('First load got: ' + d));
cachedLoader('url1').then((d) => console.log('Second load got: ' + d));
cachedLoader('url2').then((d) => console.log('Third load got: ' + d));
cachedLoader('url2').then((d) => console.log('Fourth load got: ' + d));
console.log('Waiting for load to complete');