9

ServiceWorker is a new api available in Chrome. One of the many things it lets you do is intercept network requests and respond with a cached version. I'm implementing a "take this offline" button which dynamically adds things to the cache. I'd like to report to the user how much space I'm using, and how many entries I've put in the cache.

Is it possible to query a cache to get the number of items in it? Can I report the total size of things cached in it?

Rob
  • 2,759
  • 1
  • 16
  • 11
  • 2
    As mentioned in the answer below, you can use `cacheName.keys().then(function(keys) { keys.length })`. Currently there is no way to compute the size on disk, but you can look at the `content-size` header for each response, but it will not exactly match whats stored on disk. (Also some http servers don't set content-size correctly.) There is open spec work around this with the quota-api and on ServiceWorkers here: https://github.com/slightlyoff/ServiceWorker/issues/587 – Ben Kelly Feb 05 '15 at 14:56
  • 1
    Thanks @BenKelly for the link to the discussion on that github issue. I'll weigh in with my 2 cents. – Rob Feb 05 '15 at 15:40

2 Answers2

9

You can do something like the following to find the approximate size of the cache:

// returns approximate size of a single cache (in bytes)
function cacheSize(c) {
  return c.keys().then(a => {
    return Promise.all(
      a.map(req => c.match(req).then(res => res.clone().blob().then(b => b.size)))
    ).then(a => a.reduce((acc, n) => acc + n, 0));
  });
}

// returns approximate size of all caches (in bytes)
function cachesSize() {
  return caches.keys().then(a => {
    return Promise.all(
      a.map(n => caches.open(n).then(c => cacheSize(c)))
    ).then(a => a.reduce((acc, n) => acc + n, 0));
  });
}

There's a few caveats:

  • Counts the size of the response body only. (This could be partially fixed.)
  • Counts non-opaque responses. (This can't be fixed.)
mjs
  • 63,493
  • 27
  • 91
  • 122
3

Apparently you can use cacheName.keys().length as shown in trained to thrill, you can also cycle on the single entries and compute the total weight.

Sandro Paganotti
  • 2,295
  • 16
  • 12
  • Thanks for the github source link. I can see that will work for my purposes but seems like it could be possibly expensive to loop through all of the items in the cache to add up the size. Depending on the cache implementation, that could be a lot of reads. Ideally the cache object would keep a tally of the size of the items it contains and update it as items are added and removed. – Rob Feb 05 '15 at 15:39
  • return caches.open(CACHE_NAME) .then(function (cache) { cache.keys().then(function (keys) { cachedItemCount = keys.length; }); }); – Dave S Feb 28 '20 at 19:38