JavaScript Async - Cache
Written by Ian Elliot   
Monday, 06 May 2019
Article Index
JavaScript Async - Cache
An Example

The cache API is closely associated with Progressive Web Apps but it can be used in any JavaScript program to good effect. This  extract from my recently published book JavaScript Async: Events Callbacks, Promises & Async/Await explains how promises make it ease.

 

Now Available as a Book:

 JavaScript Async

cover

You can buy it from: Amazon

Contents

  1. Modern JavaScript (Book Only)
  2. Events,Standard & Custom
  3. The Callback
      extract - The Callback & The Controller
  4. Custom Async - setTimeout, sendMessage & yield
      extract - Custom Async
      extract - Avoiding State With Yield 
  5. Worker Threads
      extract - Basic Worker ***NEW
      extract - Advanced Worker Threads 
  6. Consuming Promises 
  7. Producing Promises
      extract - The Revealing Constructor Pattern
     
    extract - Returning Promises
     
    extract - Composing Promises
  8. The Dispatch Queue
      extract - Microtasks
  9. Async & Await
      extract -  Basic Async & Await
      extract -  DoEvents & Microtasks
  10. Fetch, Cache & Service Worker
      extract - Fetch  
      extract - Cache
     
    extract -  Service Workers

Cache

The cache API is a replacement for appCache and it is much more flexible. Its basic operation is very simple. The CacheStorage object stores a set of Cache objects each of which stores a set of key value pairs.

The key is a request object and the value is a response object.

That is, a Cache object stores request/value pairs and the CacheStorage object stores Cache objects.

The idea is that you can segment your cache storage scheme into different Cache objects which you can then use via the CacheStorage object. In the simplest situation you can just use a single Cache object for everything you want to store, but even here you have to think about the possibility of supporting versioning with multiple Cache objects.

The CacheStorage object keeps an index by name of the Cache objects you create. You can use its open method to create and/or retrieve a Cache object by name, and the match method will search all of the Cache objects for the first occurrence of the request object and return its associated response object. Notice that if there are multiple Cache objects storing the same request/response pair, the one you get is the one that was created first. If you want more control you should use open to retrieve the particular Cache object and then use its match method to retrieve the request/response pair from it.

The final part of the puzzle is that the global CacheStorage object is called caches. So to create a new Cache object you would write:

var myCache=await caches.open("myCache");

If the cache already exists it is just opened ready for use.

All of the Cache methods are asynchronous and return Promise objects or arrays of Promise objects.

To store a new key/value pair in the cache you would use either:

await myCache.add(request);

which loads the response from request and stores both or:

await myCache.put(request,response);

which stores the request and response pair in the cache without fetching anything new.

There is also addAll which will add an array of requests and their response objects freshly download.

There is a complication here.

When you use add or addAll the response is downloaded and the body is also downloaded and stored in the cache in a raw form. When you use put the response isn’t downloaded again, but the body has to be stored in the cache in raw form. If you have used any of the commands that set the body data to a particular type then it will not be stored in the cache and you will generate an exception.

Another way to say this is that the body cannot be used before it is put into the cache. You also cannot use the body of a response after it has been put into the cache. To use it you have to retrieve it from the cache.

For example if you try:

var response = await fetch(request);
await myCache.put(request,response);

you will find that it works and the request/response pair are stored in the cache. However, you cannot use the response body after this. That is if you now try:

var text=await response.text();

you will see and error that says:

Uncaught (in promise) TypeError: Already read

You can only read the body data in once and adding a response to the cache reads it and you cannot read it a second time. In the same way if you use the body before putting the response in the cache you will see the same error.

When you store a response in the cache its body is streamed and stored and cannot be streamed a second time.

To find something already stored in the cache you can use:

await myCache.match(request,options);

which returns the first response objects in the cache or:

await myCache.matchAll(request,options)

which returns an array of Promises with all of the response objects that match the request.



Last Updated ( Monday, 06 May 2019 )