I've got the following code that retrieves data asynchronously and caches it for performance optimization purposes:
let cache = {}
const optimizedFetch = 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 response keyed to url
cache[url] = json
return json
}
catch (error) {
console.log(error)
}
}
optimizedFetch("https://jsonplaceholder.typicode.com/todos").then(console.log)
The approach above works fine but if a second request to the same url comes while the first one is still awaited then a second fetch will be fired.
How can I improve that scenario?
let cache = {};
let awaits = {};
const optimizedFetch = (url) => {
return new Promise((resolve, reject) => {
if (url in cache) {
// return cached result if available
console.log("cache hit");
return resolve(cache[url]);
}
if (url in awaits) {
console.log("awaiting");
awaits[url].push({
resolve,
reject
});
return;
}
console.log("first fetch");
awaits[url] = [{
resolve,
reject
}];
fetch(url)
.then(response => response.json())
.then(result => awaits[url].forEach(({
resolve
}) => resolve(result)))
.catch(error => awaits[url].forEach(({
reject
}) => reject(error)))
.finally(() => {
delete awaits[url];
});
});
};
optimizedFetch("https://jsonplaceholder.typicode.com/todos")
.then(({
length
}) => console.log(length));
optimizedFetch("https://jsonplaceholder.typicode.com/todos")
.then(({
length
}) => console.log(length));