简体   繁体   English

如何从在 Node 中使用 fetch 的异步函数缓存数据

[英]How to cache data from async function that uses fetch in Node

I was trying to see if there was a way to cache a json response from a fetch async call, possibly using LRU.我试图看看是否有办法缓存来自 fetch 异步调用的 json 响应,可能使用 LRU。

I've tried using several packages, such as node-cache and lru-cache, but I don't think they worked because my function is asynchronous.我尝试过使用多个包,例如 node-cache 和 lru-cache,但我认为它们不起作用,因为我的函数是异步的。

This is what my fetch function basically looks like:这就是我的 fetch 函数的基本样子:

const jsonFetch = async (url) => {
    try {
        const response = await fetch (url)
        const json = await response.json();
        return json
    }
    catch (error) {
        console.log(error)
    }
}

For example, if I get someone to hit my route 20 times in a minute, I'd like to easily fetch the data and return the response within 0.03 ms instead of 0.3 ms.例如,如果我让某人在一分钟内点击我的路线 20 次,我希望轻松获取数据并在 0.03 毫秒而不是 0.3 毫秒内返回响应。 Currently, it is always using the a URL to fetch the data.目前,它总是使用 URL 来获取数据。

This has been here for a while, but I agree with the comment from @sleepy012.这已经有一段时间了,但我同意@sleepy012 的评论。 If I wanted to avoid parallel calls, the trick should be to cache the promise, not only the value.如果我想避免并行调用,诀窍应该是缓存承诺,而不仅仅是价值。 So something like this should work:所以这样的事情应该有效:

 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');

There's nothing about async functions that will prevent caching results.异步函数不会阻止缓存结果。 It's possible the libraries you're looking at can't handle the promises, but here's a basic proof of concept that might help to get things started:您正在查看的库可能无法处理承诺,但这里有一个基本的概念证明,可能有助于开始工作:

 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)

You will only get cache hits on requests made after the first request returns a value to cache您只会第一个请求返回缓存值的请求中获得缓存命中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM