Service Worker cache – able to put but not able to retrieve

  Kiến thức lập trình

I created a Service Worker that caches the results of nearmap and metromap tiles for a longer period of time. See below code.

const version = 10;
const CACHE_NAME = `mapbox-tiles-nearmap-${version}`;
const periodForTiles = (1000 * 60 * 60 * 24 * 356) / 2; // half year
const listResorcesForCache = ['api.nearmap.com/tiles', 'api-v3.metromap.com.au/tiles'];

self.addEventListener('fetch', event => {
    if (isCachedResource(event.request.url)) {
        event.respondWith(fromCacheOrNetwork(event.request));
    } else {
        event.respondWith(fromNetwork(event.request));
    }
});

async function fromCacheOrNetwork(request) {
    const cache = await caches.open(CACHE_NAME);
    const response = await cache.match(request, {ignoreVary: true});

    console.log('test', {cache, response});
    // @todo: this is where the issue is, the response is always undefined

    return isFresh(response) ? response : fromNetwork(request);
}
function fromNetwork(request) {
    return fetch(request.clone())
        .then(function (response) {
            if (isCachedResource(request.url) && response.status < 300) {
                cachePut(request, response);
            }
            return response;
        })
        .catch(function (error) {
            // This catch() will handle exceptions that arise from the match() or fetch() operations.
            // Note that a HTTP error response (e.g. 404) will NOT trigger an exception.
            // It will return a normal response object that has the appropriate error code set.
            console.error('  Error in fetch handler:', error);
            throw error;
        });
}
async function cachePut(request, response) {
    const options = {
        status: response.status,
        statusText: response.statusText,
        headers: new Headers(),
    };
    response.headers.forEach((v, k) => options.headers.set(k, v));
    options.headers.set(
        'Expires',
        new Date(Date.now() + periodForTiles).toUTCString()
    );
    const clonedResponse = response.clone();

    const cache = await caches.open(CACHE_NAME);
    cache.put(request, new Response(clonedResponse.body, options));
}
function isFresh(response) {
    if (!response) return false;

    const expires = new Date(response.headers.get('Expires'));
    return expires > Date.now();
}

function isCachedResource(url) {
    return (
        undefined !==
        listResorcesForCache.find(item => {
            return url.includes(item);
        })
    );
}

Currently, the code is able to intercept the fetch requests from nearmap and metrop and store the result to Cache Storage. However, when I to fetch from cache, it is always returning “undefined” based on the result returned from cache.match(). Any idea why it’s able to store but not able to retrieve?

I have tried adding ignoreVary option on the cache.match() function but it still returned undefined.

New contributor

slapchuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

LEAVE A COMMENT