Search code examples
timeoutfetchservice-worker

Service Worker caching not recognizing timeout as a function


I was watching Steve Sanderson's NDC presentation on up-and-coming web features, and saw his caching example as a prime candidate for an application I am developing. I couldn't find the code, so I have typed it up off the Youtube video as well as I could.

Unfortunately it doesn't work in Chrome (which is also what he is using in the demo) It fails with Uncaught TypeError: fetch(...).then(...).timeout is not a function at self.addEventListener.event.

I trawled through Steve's Github, and found no trace of this, nor could I find anything on the NDC Conference page

//inspiration: 
//            https://www.youtube.com/watch?v=MiLAE6HMr10

//self.importScripts('scripts/util.js');

console.log('Service Worker script running');
self.addEventListener('install', event => {
    console.log('WORKER: installing');
    const urlsToCache = ['/ServiceWorkerExperiment/', '/ServiceWorkerExperiment/scripts/page.js'];
    caches.delete('mycache');
    event.waitUntil(
            caches.open('mycache')
            .then(cache => cache.addAll(urlsToCache))
            .then(_ => self.skipWaiting())
            );
});
self.addEventListener('fetch', event => {
    console.log(`WORKER: Intercepted request for ${event.request.url}`);
    if (event.request.method !== 'GET') {
        return;
    }

    event.respondWith(
            fetch(event.request)
            .then(networkResponse => {
                console.log(`WORKER: Updating cached data for ${event.request.url}`);
                var responseClone = networkResponse.clone();
                caches.open('mycache').then(cache => cache.put(event.request, responseClone));
                return networkResponse;
            })
            //if network fails or is too slow, return cached data
            //reference for this code: https://youtu.be/MiLAE6HMr10?t=1003
            .timeout(200) 
            .catch(_ => {
                console.log(`WORKER: Serving ${event.request.url} from CACHE`);
                return caches.match(event.request);
            })
            );
});

As far as I read the fetch() documentation, there is no timeout function, so my assumption is that the timeout function is added in the util.js which is never shown in the presentation... can anyone confirm this? and does anyone have an Idea about how this is implemented?


Solution

  • Future:

    It's coming.

    According to Jake Archibald's comment on whatwg/fetch the future syntax will be:

    Using the abort syntax, you'll be able to do:

    const controller = new AbortController();
    const signal = controller.signal;
    
    const fetchPromise = fetch(url, {signal});
    
    // 5 second timeout:
    const timeoutId = setTimeout(() => controller.abort(), 5000);
    const response = await fetchPromise;
    // …
    

    If you only wanted to timeout the request, not the response, add:

    clearTimeout(timeoutId);
    // …
    

    And from another comment:

    Edge & Firefox are already implementing. Chrome will start shortly.

    Now:

    If you want to try the solution that works now, the most sensible way is to use this module.

    It allows you to use syntax like:

    return fetch('/path', {timeout: 500}).then(function() {
      // successful fetch
    }).catch(function(error) {
      // network request failed / timeout
    })