I have built a web app using Backbone.js and it has lots of calls to a RESTful service and it works like a charm.
I tried adding a ServiceWorker to cache all the previous calls so they'll be available offline.
What I actually get is that the calls I do for the first time, dies with this error:
Failed to load resource: net::ERR_FAILED
However on page reload, I get it's cached data
My service worker fetch:
self.addEventListener('fetch', function(e) {
// e.respondWidth Responds to the fetch event
e.respondWith(
// Check in cache for the request being made
caches.match(e.request)
.then(function(response) {
// If the request is in the cache
if ( response ) {
console.log("[ServiceWorker] Found in Cache", e.request.url, response);
// Return the cached version
return response;
}
// If the request is NOT in the cache, fetch and cache
var requestClone = e.request.clone();
fetch(requestClone)
.then(function(response) {
if ( !response ) {
console.log("[ServiceWorker] No response from fetch ")
return response;
}
var responseClone = response.clone();
// Open the cache
caches.open(cacheName).then(function(cache) {
// Put the fetched response in the cache
cache.put(e.request, responseClone);
console.log('[ServiceWorker] New Data Cached', e.request.url);
// Return the response
return response;
}); // end caches.open
console.log("Response is.. ?", response)
return response;
})
.catch(function(err) {
console.log('[ServiceWorker] Error Fetching & Caching New Data', err);
});
}) // end caches.match(e.request)
); // end e.respondWith
});
edit: I don't think there is a need for any Backbone.js web app code. I use the fetch
method from Backbone.js models and collections. calls like https://jsonplaceholder.typicode.com/posts/1 and https://jsonplaceholder.typicode.com/posts/2
will replay show this error on first time. after refreshing the page, i do have this info without requesting. all from cache. and all other request that i still didn't do, will stay error
The only problem I see is that when the request is not in the cache, then you do a fetch
, but you do not return the result of that fetch
to the enclosing then
handler. You need to add a return
so that you have:
return fetch(requestClone)
.then(function(response) {
None of the data provided by the return
statements inside your then
handler for the fetch
will get transferred up the chain otherwise.
I also see that you do not return the promise provided by caches.open(cacheName).then...
. This may be fine if you want to decouple saving a response in the cache from returning a result up the chain, but at the very least I'd put a comment saying that that's what I'm doing here rather than leave it to the reader to figure out whether a return
statement is missing by accident, or it was done on purpose.
i solved it after searching more. Backbone.js my views in the Web app used to do:
this.listenTo(this.collection,"reset",this.render);
this.listenTo(this.collection,"add",this.addCollectionItem);
this.listenTo(this.collection,"error", this.errorRender);
while my Service worker is returning Promises.
I had to change my some code my Web app views to something like this:
this.collection.fetch({},{reset:true})
.then(_.bind(this.render, this))
.fail(_.bind(this.errorRender,this))
more or less...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.