Can attendants cache POST requests?

I tried to cache the POST request in a working application for the fetch event.

I used cache.put(event.request, response) , but the returned promise was rejected with TypeError: Invalid request method POST. .

When I tried to get into the same POST API, caches.match(event.request) gave me undefined.

But when I did the same for the GET methods, it worked: caches.match(event.request) for the GET request gave me an answer.

Can attendants cache POST requests? In case they cannot, what approach can we use to make applications truly standalone?

+17
source share
4 answers

You cannot cache POST requests using the Cache API. See https://w3c.imtqy.com/ServiceWorker/#cache-put (clause 4).

A related discussion is in the spec repository: https://github.com/slightlyoff/ServiceWorker/issues/693.

An interesting solution is presented in the ServiceWorker Cookbook: https://serviceworke.rs/request-deferrer.html Essentially, the solution serializes queries to IndexedDB.

+21
source

I used the following solution in a recent GraphQL API project: I cached all the API route responses in the IndexedDB object store using a serialized representation of the request key as a cache. Then I used the cache as a reserve if the network was unavailable:

 // ServiceWorker.js self.addEventListener('fetch', function(event) { // We will cache all POST requests to matching URLs if(event.request.method === "POST" || event.request.url.href.match(/*...*/)){ event.respondWith( // First try to fetch the request from the server fetch(event.request.clone()) // If it works, put the response into IndexedDB .then(function(response) { // Compute a unique key for the POST request var key = getPostId(request); // Create a cache entry var entry = { key: key, response: serializeResponse(response), timestamp: Date.now() }; /* ... save entry to IndexedDB ... */ // Return the (fresh) response return response; }) .catch(function() { // If it does not work, return the cached response. If the cache does not // contain a response for our request, it will give us a 503-response var key = getPostId(request); var cachedResponse = /* query IndexedDB using the key */; return response; }) ); } }) function getPostId(request) { /* ... compute a unique key for the request incl. it body: eg serialize it to a string */ } 

Here is the complete code for my specific solution using Dexie.js as IndexedDB-wrapper. Feel free to use it!

+3
source

If you are talking about form data, you can capture the sample event and read the form data as shown below, and then save the data in indexedDB.

 //service-worker.js self.addEventListener('fetch', function(event) { if(event.request.method === "POST"){ var newObj = {}; event.request.formData().then(formData => { for(var pair of formData.entries()) { var key = pair[0]; var value = pair[1]; newObj[key] = value; } }).then( ...save object in indexedDB... ) } }) 
+1
source

Another approach to providing full offline mode can be obtained by using Cloud Firestore offline storage .

POST / PUT requests are executed in the local cached database and then automatically synchronized with the server as soon as the user restores the Internet connection (note that there is a limit of 500 offline requests).

Following this decision, another aspect should be taken into account: if several users have offline changes that are synchronized at the same time, there is no guarantee that the changes will be made in the correct chronological order on the server, since Firestore uses the "first come - first served. " logics.

0
source

Source: https://habr.com/ru/post/1242538/


All Articles