0

I want to get a list of all the different caches existing in the Cache API and how many assets each cache has. Even though I have managed to return the Map object with the info, when calling Map.get(cacheName) I get undefined.

I've seen that once the page has loaded, if I manually run 'cacheInfo = getCacheInfo()', then the cacheInfo.get() works.

function getCacheInfo() {
  const cacheMap = new Map();
  window.caches.keys().then(function(cacheNames) {
    cacheNames.forEach(function(cacheName) {
      window.caches
        .open(cacheName)
        .then(function(cache) {
          cacheMap.set(cacheName, 0);
          return cache.keys();
        })
        .then(function(requests) {
          requests.forEach(function(request) {
            cacheMap.set(cacheName, cacheMap.get(cacheName) + 1);
          });
        });
    });
  });
  return cacheMap;
}

async function printTable() {
  const cacheInfo = await getCacheInfo();
  console.log(cacheInfo);
  console.log(cacheInfo.get('html-cache')); // Returns undefined
}

printTable();
AgoHH
  • 180
  • 1
  • 14
  • `getCacheInfo()` needs to be declared `async`. – Barmar Nov 01 '19 at 00:49
  • The question says that the problem is in `cacheMap.get(cacheName)`, but the comment in the code says it's at `cacheInfo.get('html-cache')`. Which is it? – Barmar Nov 01 '19 at 00:51
  • `getCacheInfo` needs to return a promise that resolves at the end of the final `then` callback. – George Nov 01 '19 at 00:51
  • @George Declaring it `async` will make that happen automatically, right? – Barmar Nov 01 '19 at 00:51
  • @Barmar but that still won't fix it as it's not resolving inside the then. If you convert from `.then` syntax to `await` syntax, then it would work. – George Nov 01 '19 at 00:53
  • Right, `return cacheMap` is outside all the asynchronous stuff, so it's being returned before any of the callbacks fill in the map. – Barmar Nov 01 '19 at 00:56
  • yes in fact another flaw is the forEach. The code should instead use something like `Promise.all` and map an array of promises for it. – George Nov 01 '19 at 01:03

1 Answers1

1

You mix async/await with .then syntaxes, for what? Best practice is just using async/await or Promise solving syntax, not both.

For your case, I think async/await is a best choice, I convert your code to use async/await syntax. I think you need (maybe) read more about Promise, async/await to understand them.

async function getCacheInfo() {
  const cacheMap = new Map();
  const cacheNames = await window.caches.keys();
  for (const cacheName of cacheNames) {
    const cache = await window.caches.open(cacheName);
    cacheMap.set(cacheName, 0);

    const requests = await cache.keys();
    requests.forEach((request) => {
      cacheMap.set(cacheName, cacheMap.get(cacheName) + 1);
    });
  }
  return cacheMap;
}

async function printTable() {
  const cacheInfo = await getCacheInfo();
  console.log(cacheInfo);
  console.log(cacheInfo.get('html-cache')); // Returns undefined
}

(async () => {
  await printTable();
})();
hoangdv
  • 15,138
  • 4
  • 27
  • 48
  • The main point here is to replace `.forEach` and `.then` with `for` and `await`, as the second one really waits for the asynchronous task to finish vefore returning. For sure this will be a lot slower, might consider using `await Promise.all(arr.map(...))` instead of the for loop. – Jonas Wilms Nov 01 '19 at 01:27