Javascript 服务人员可以缓存POST请求吗?

Javascript 服务人员可以缓存POST请求吗?,javascript,post,request,service-worker,pwa,Javascript,Post,Request,Service Worker,Pwa,我试图在获取事件时在服务工作者中缓存POST请求 我使用了cache.put(event.request,response),但返回的承诺被TypeError:Invalid request method POST.拒绝。 当我尝试使用相同的POST API时,caches.match(event.request)给了我未定义的消息 但是当我对GET方法做同样的操作时,它起了作用:caches.match(event.request)对于GET请求,它给了我一个响应 服务人员可以缓存POST请求

我试图在获取事件时在服务工作者中缓存POST请求

我使用了
cache.put(event.request,response)
,但返回的承诺被
TypeError:Invalid request method POST.拒绝。

当我尝试使用相同的POST API时,
caches.match(event.request)
给了我未定义的消息

但是当我对GET方法做同样的操作时,它起了作用:
caches.match(event.request)
对于GET请求,它给了我一个响应

服务人员可以缓存POST请求吗?
如果他们不能,我们可以使用什么方法使应用程序真正离线?

您不能使用缓存API缓存POST请求。见(第4点)

规范存储库中有一个相关的讨论:

一个有趣的解决方案出现在ServiceWorker食谱中:
基本上,该解决方案将对IndexedDB的请求序列化。

如果您谈论的是表单数据,那么您可以截获fetch事件并以如下类似的方式读取表单数据,然后将数据保存在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... )
      }
})

我在最近的一个GraphQLAPI项目中使用了以下解决方案:我使用请求的序列化表示作为缓存键,将来自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包装器的特定解决方案的示例。请随意使用它

另一种提供完整离线体验的方法是使用

POST/PUT请求在本地缓存数据库上执行,然后在用户恢复其internet连接时自动同步到服务器(请注意,脱机请求的数量限制为500个)

遵循此解决方案需要考虑的另一个方面是,如果多个用户的脱机更改同时同步,则不保证这些更改将按正确的时间顺序在服务器上执行,因为Firestore使用先到先得的逻辑。

根据(第4点)


简单地尝试一下应该很容易:)虽然这个链接可以回答这个问题,但最好在这里包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-对不起。我已经更改了答案以包含代码摘要(整个代码相当长)。或者,我应该发布整个代码,而不管它的长度如何?一个片段就可以了。如果你只是在自己的博客上发布一个链接,它看起来很像垃圾邮件。现在对我来说似乎好多了。如果你想推广你的博客,我可能会建议你阅读下面的内容。我没有看到任何关于补丁或删除请求的内容。是一样的吗?补丁和删除应该是一样的。您将在服务工作者中获得一个“fetch”事件,您可以检查方法——get、POST、PATCH、DELETE——并执行您需要执行的任何操作。
        if(request.method !== "GET") {
            return Promise.reject('no-match')
        }