question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

fetchDidFail with StaleWhileRevalidate is not called

See original GitHub issue

Library Affected: workbox v5.1.3 npm

Browser & Platform: Google Chrome v85

Issue or Feature Request Description: I don’t seem to get how to run some code when a fetch in a StaleWhileRevalidate strategy fails. I’d like to use the callback to detect offline usage, but fetchDidFail is not called when I tick “offline” and reload the pahe. (fetchDidSucceed works tho). Is this expected? I didn’t find any mention of that in the documentation.

Here’s an example:

const messageIfFail: WorkboxPlugin = {
    fetchDidFail: async function () {
        // No return expected.
        // NOTE: `originalRequest` is the browser's request, `request` is the
        // request after being passed through plugins with
        // `requestWillFetch` callbacks, and `error` is the exception that caused
        // the underlying `fetch()` to fail.
        while (true) {
            console.log("called");
        }
        // send message to client
    }
}

registerRoute(
    ({url}) => {
        return url.origin == "https://fonts.googleapis.com"
            || url.origin == "https://cdn.jsdelivr.net"
    },
    new StaleWhileRevalidate({
        cacheName: 'cdn',
        plugins: [
            messageIfFail
        ]
    })
);

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:16 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
jeffposnickcommented, Sep 10, 2020

When attempting to debug this, I would suggest starting fresh from an Incognito window, and additionally, not checking Disable Cache. It sounds like you’ve made a number of changes to your SW during development, and it would be good to rule out inconsistent cache state (using the Incognito window) while also replicating what users will actually see in production (don’t check Disable Cache).

You might see a log message about a failed fetch() made by StaleWhileRevalidate in development, but if the strategy uses a cached response from the Cache Storage API to satisfy the request, the “catch” handler won’t run. The “catch” handler only runs when there’s no response (from fetch() or Cache Storage API) that can be used by a strategy.

FWIW, your code could be simplified to:

registerRoute(
    ({url}) => {
        return url.origin === "https://fonts.googleapis.com"
            || url.origin === "https://cdn.jsdelivr.net"
    },
    new StaleWhileRevalidate({
      cacheName: 'cdn',
      plugins: [...],
    })
});

setCatchHandler(async () => { //doesn't get called in my situation
    console.log("TEST");
    return Response.error();
});
1reaction
jeffposnickcommented, Sep 9, 2020

fetchDidFail will execute when the underlying fetch() fails when using StaleWhileRevalidate, even if the strategy ends up using a response from the Cache Storage API.

I see from your sample route that you’re attempting to use this with subresources loaded from a CDN, and in most cases, responses to those sorts of URLs will use long-lived Cache-Control headers that don’t require revalidation. So what my guess is as to what’s happening is that even when you’re offline, the underlying fetch() request succeeds, rather than fails, since a cache hit in the browser’s “normal” HTTP cache is sufficient, and fetch() never ends up going against the network anyway.

You can see this in action at https://glitch.com/edit/#!/upbeat-rebel-octopus?path=sw.js, where the example is for a HTTP response that has a maximum age of 20 seconds. If you go offline and try again within 20 seconds of populating the “normal” HTTP cache with a response, then the fetch() will be fulfilled from the HTTP cache. If you wait longer than 20 seconds, then the response in the HTTP cache will be considered too old to use without revalidation, and the fetch() will fail when it makes the network request to revalidate.

I’m going to close this for now, but if I’m misinterpreting anything, let me know and we can revisit.

Read more comments on GitHub >

github_iconTop Results From Across the Web

workbox-strategies - Chrome Developers
When a strategy instance is registered with a Workbox workbox-routing. Route , this method is automatically called when the route matches.
Read more >
workbox - Postprocess page content with staleWhileRevalidate
You're correct in that there's no RequestWrapper lifecycle event that corresponds to a network request being successfully returned.
Read more >
Cache Storage Is Empty When Using Workbox With Cdn
An implementation of a stalewhilerevalidate request strategy. If the network request fails and there is no cache match this will When a strategy...
Read more >
Keeping things fresh with stale-while-revalidate - web.dev
stale-while-revalidate helps developers balance between immediacy—loading cached content right away—and freshness—ensuring updates to the ...
Read more >
ResourcePlugin | react-suspense-cache - LXSMNSYC
Called during the cache fetching and cache writing stage. ... Optional fetchDidFail. fetchDidFail: undefined | ((param: FetchDidFailParam<T>) ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found