webentwicklung-frage-antwort-db.com.de

Kann Servicemitarbeiter zwischenspeichern POST Wünsche?

Ich habe versucht, eine POST - Anforderung in einem Service Worker beim Abrufereignis zwischenzuspeichern.

Ich habe cache.put(event.request, response) verwendet, aber das zurückgegebene Versprechen wurde mit TypeError: Invalid request method POST. abgelehnt.

Als ich versuchte, die gleiche POST - API zu treffen, gab mir caches.match(event.request) undefined.

Aber als ich das gleiche für GET-Methoden tat, funktionierte es: caches.match(event.request) für eine GET-Anfrage gab mir eine Antwort.

Können Service-Mitarbeiter POST -Anforderungen zwischenspeichern? Falls dies nicht möglich ist, mit welchem ​​Ansatz können wir Apps wirklich offline machen?

15
Aniket

Sie können POST -Anforderungen nicht mit der Cache-API zwischenspeichern. Siehe https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-put-method (Punkt 2.2).

Es gibt eine verwandte Diskussion im Spec-Repository: https://github.com/slightlyoff/ServiceWorker/issues/693

Eine interessante Lösung ist die im ServiceWorker-Kochbuch dargestellte Lösung: https://serviceworke.rs/request-deferrer.html .__ Die Lösung serialisiert Anforderungen grundsätzlich an IndexedDB.

20
Marco

Ich habe die folgende Lösung in einem aktuellen Projekt mit einer GraphQL-API verwendet: Ich habe alle Antworten von API-Routen in einem IndexedDB-Objektspeicher mit einer serialisierten Darstellung der Anforderung als Cache-Schlüssel zwischengespeichert. Dann habe ich den Cache als Fallback verwendet, wenn das Netzwerk nicht verfügbar war:

// 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's body: e.g. serialize it to a string */
}

Hier ist der vollständiger Code für meine spezifische Lösung, die Dexie.js als IndexedDB-Wrapper verwendet. Fühlen Sie sich frei, es zu benutzen!

3
A. Kabachnik

Ein anderer Ansatz, um ein vollständig offline Erlebnis zu erzielen, kann mithilfe von Cloud Firestore-Offline-Persistenz erzielt werden.

POST/PUT-Anforderungen werden in der lokal zwischengespeicherten Datenbank ausgeführt und dann automatisch mit dem Server synchronisiert, sobald der Benutzer seine Internetverbindung wiederherstellt (beachten Sie jedoch, dass es ein Limit von 500 Offline-Anforderungen gibt).

Ein weiterer Aspekt, der bei dieser Lösung berücksichtigt werden muss, ist, dass bei gleichzeitiger Synchronisierung mehrerer Benutzer von Offline-Änderungen nicht garantiert wird, dass die Änderungen in der richtigen chronologischen Reihenfolge auf dem Server ausgeführt werden, da Firestore ein Wer zuerst kommt, mahlt zuerst Logik.

0
Francesco

Wenn Sie über Formulardaten sprechen, können Sie das Abrufereignis abfangen und die Formulardaten auf ähnliche Weise wie unten lesen und dann die Daten in indexedDB speichern.

//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... )
      }
})
0
Roman Gherta

Laut https://w3c.github.io/ServiceWorker/#cache-put (Punkt 4).

        if(request.method !== "GET") {
            return Promise.reject('no-match')
        }
0