web-dev-qa-db-ja.com

サービスワーカーはPOSTリクエストをキャッシュできますか?

フェッチイベントでService WorkerでPOSTリクエストをキャッシュしようとしました。

cache.put(event.request, response)を使用しましたが、返されたプロミスは_TypeError: Invalid request method POST._で拒否されました。

同じPOST API)をヒットしようとしたとき、caches.match(event.request)は未定義を与えていました。

しかし、GETメソッドに対して同じことをしたとき、それは機能しました:GET要求のcaches.match(event.request)は応答を与えていました。

サービスワーカーはPOSTリクエストをキャッシュできますか?できない場合、アプリを本当にオフラインにするためにどのようなアプローチを使用できますか?

21
Aniket

GraphQL APIを使用した最近のプロジェクトでは、次のソリューションを使用しました。APIキーからのすべての応答をIndexedDBオブジェクトストアのキャッシュキーとして要求のシリアル化された表現を使用してキャッシュしました。次に、ネットワークが利用できない場合のフォールバックとしてキャッシュを使用しました。

// 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 */
}

以下は、Dexie.jsをIndexedDBラッパーとして使用する特定のソリューションの 完全なコード です。気軽に使用してください!

5
A. Kabachnik

フォームデータについて話している場合は、フェッチイベントをインターセプトし、以下と同様の方法でフォームデータを読み取り、データを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
Roman Gherta

完全なオフライン体験を提供する別のアプローチは、 Cloud Firestore offline persistence を使用して取得できます。

POST/PUTリクエストはローカルキャッシュデータベースで実行され、ユーザーがインターネット接続を復元するとすぐにサーバーに自動的に同期されます(ただし、オフラインリクエストの数は500に制限されています)。

このソリューションに従うことで考慮すべきもう1つの側面は、複数のユーザーが同時に同期されるオフライン変更を持っている場合、Firestoreが先着順ロジック。

0
Francesco

https://w3c.github.io/ServiceWorker/#cache-put (ポイント4)による。

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