3

Cache API in JavaScript - with just 20 lines of code.

 1 year ago
source link: https://dev.to/rajeshroyal/cache-api-in-javascript-with-just-20-lines-of-code-49kg
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Cover image for Cache API in JavaScript - with just 20 lines of code.
Rajesh Royal

Posted on May 15

• Updated on May 17

Cache API in JavaScript - with just 20 lines of code.

let cache = {};
async function getData(url){
    let result = "";
    if(cache[url] !== undefined) return cache[url].value;

    await fetch(url)
    .then(response => response.json())
    .then(json => cache[url] = {time: new Date(), value: json});

    return cache[url].value;
}

// Interval to clear cache;
setInterval(function (){
    if(Object.keys(cache).length > 0){
        let currentTime = new Date();
        Object.keys(cache).forEach(key => {
            let seconds = currentTime - cache[key].time;

            if(seconds > 10000){
                delete cache[key];
                console.log(`${key}'s cache deleted`)
            }
        })
    }
}, 3000);

Now you can call your API's like this.

getData("https://jsonplaceholder.typicode.com/todos/1")
.then(data => console.log(data));

If there is a cache value of the current api call then it will return values from cache otherwise call the api and return data while adding the response to cache.

Preview

Image Cache API in JavaScript - with just 20 lines of code

I'm assuming this is much better than RTK Query and React Query 😅.

Discussion (10)

pic

CollapseExpand

Just out of curiosity why are you calling:

let currentTime = new Date();

inside of .forEach? Why not assign it before the call:

 let currentTime = new Date();
 Object.keys(cache).forEach(key => {
            let seconds = currentTime - cache[key].time;
            ...

this way you only pay for the overhead of calling Date once.

I expect new Date() to be practically a constant (maybe 100ms difference) over the time spent clearing the cache. Since every three seconds you are clearing anything in the cache older than 10 seconds.

Calling new Date() IIUC is expensive since it has to reach down to the operating system to get the date value.

True some item might linger in the cache for 100 ms longer but....

Comment button Reply

CollapseExpand

Author

May 16

Good correction, I will update the code.

Also I didn't write it to be optimised. I was just experimenting how caching works simply and pasted same code here 😀.

Comment button Reply

CollapseExpand

It's good that you shared interesting material, but remember that not all developers know, are thinking and/or working on optimizing their scripts. There are beginners, and perhaps not only beginners, who, seeing interesting code at first glance, copy it into their applications and use it without checking or optimizing, and then other people may suffer from sudden errors that can come out absolutely by accident.

It is necessary to approach operations related to cycles carefully and try to think through the work of the function in advance, since even any small error can entail a bunch of others that can cause unnecessary memory costs or something else, perhaps. Lol.

I wish you good luck.

Thread

Thread

CollapseExpand

Nice idea to use Memoized results.Thanks!!

Comment button Reply

CollapseExpand

What happen if you get the same data at the same url very closely, the first call didn't finished so you make two calls instead of one

Comment button Reply

CollapseExpand

Author

May 18

Didn't understand much, can you please explain a bit more.

Comment button Reply

CollapseExpand

Note: if you need caching for production projects, I highly recommend searching for existing implementations (or at least existing algorithms).

Otherwise I have some notes:

  1. The current implementation only accepts the URL. But usually the same URL is used with different parameters, http methods or headers. Because not all of the possible keys can be mapped, I recommend accepting a key, and a function (to be used if the key is missing).
  2. Some data will need to be cached for different amount of time, so accepting a parameter for it is a good idea. That would mean using a setInterval for each key, or replacing the cache[key].time with a validUntil time object.
  3. Because you are deleting the cache after a fixed point of time, there is no need to keep the cache centralized, and it will be easier to just implement a memoize function that deleted the cache after a certain amount of time.
function memoize(fn, delAfter = 1000000) {
  const missing = Symbol("missing");
  let cache = missing;
  return async () => {
    if (cache === missing) {
       cache = Promise.resolve(fn());
       setTimeout(() => cache = missing, delAfter);
    }
    return await cache;
  }
}
const foo = memoize(() => fetch("https://foo/bar", { method: " POST", body: JSON.stringify({bar:1}) }))

// Will only do a single fetch.
console.log(await foo(), await foo())

Comment button Reply

CollapseExpand

Can I ask you why are you doing this:

await fetch(url)
    .then(response => response.json())
    .then(json => cache[url] = {time: new Date(), value: json})

Instead of this:

const response = await fetch(url)
cache[url] = { time: new Date(), value: response.json()

If you use await you can replace those .then and I think this is much more cleaner :D

Comment button Reply

CollapseExpand

Great job. Thanks for sharing.

Comment button Reply


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK