Reputation: 3057
I'm wanting to cache volatile data with my service worker. My thought is to return first with the possibly stale cache match, and simultaneously fire off the fetch request and return that data if/when the fetch is successful.
This is the code I'm running for non-volatile data that I want to cache:
return e.respondWith(
caches.match(request.url).then(function(cacheResponse) {
// Found it in the cache
if (cacheResponse) {
console.log('[ServiceWorker] Found it in Cache')
return cacheResponse
// Not in the cache
} else {
console.log('[ServiceWorker] Not in Cache')
return fetch(request).then(function(fetchResponse) {
console.log('[ServiceWorker] Fetched from API', fetchResponse)
// don't cache errors
if (!(fetchResponse && fetchResponse.status === 200)) {
console.log('[ServiceWorker] Fetch error, no cache')
return fetchResponse
}
return caches.open(cacheName).then(function(cache) {
cache.put(request.url, fetchResponse.clone())
console.log('[ServiceWorker] Fetched and Cached Data', request.url)
return fetchResponse
})
})
}
})
)
How would I return both the cachedResponse
and the fetchResponse
asynchronously? Is this possible?
UPDATE:
I've read Jake Archibald's offline cookbook where he talks about cache then network, which is exactly what I'm wanting to do, but it appears you need to add code everywhere you make a call where you want this 'cache then network' service.
I was hoping that there would be a way to do this directly from the service worker, though I'm not sure it's possible, since once you return with cached data how could you also return fetch data without making the exact same request again from the page?
Thanks for the help!
Upvotes: 2
Views: 1257
Reputation: 5253
It's not possible to return two responses from the SW to the page as far as I know.
What you can do, for instance, is to use the PostMessage or Broadcast Channel APIs to send a message from the SW to the page with the fresh data. Basically you would request something from the page using the Fetch API, then return cached data from the SW and at the same time initiate a network request, then refresh the cache with whatever the SW received from the network, and lastly if the response was something new, notify the page via PostMessage that "hey, there's a new version available, take it here: { data }".
This, however, might not be any better than what you saw in the Offline Cookbook, and could actually make you write more code. You would somehow need to manage the messages (with fresh data) from the SW and keep track of what data to update on the page etc.
What I would do if I understand you correctly: generalize the Offline Cookbook idea in a function that can be used instead of simple Fetch request and make it return a Promise. It should be fairly simple to go through the code and replace fetch() calls with customFetch() calls and keep all the Caches API/SW logic somewhere else.
Upvotes: 3