首页 文章

服务工作者可以缓存POST请求吗?

提问于
浏览
16

我尝试在fetch事件中缓存服务工作者的POST请求 .

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

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

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

服务工作者可以缓存POST请求吗?如果他们不能,我们可以使用什么方法使应用程序真正脱机?

3 回答

  • 20

    您无法使用Cache API缓存POST请求 . 见https://w3c.github.io/ServiceWorker/#cache-put(第4点) .

    规范库中有相关的讨论:https://github.com/slightlyoff/ServiceWorker/issues/693

    一个有趣的解决方案是ServiceWorker Cookbook中提供的解决方案:https://serviceworke.rs/request-deferrer.html该解决方案基本上将请求序列化为IndexedDB .

  • 0

    我在最近使用GraphQL API的项目中使用了以下解决方案:我使用Request as cache cache key的序列化表示来缓存IndexedDB对象存储中API路由的所有响应 . 然后,如果网络不可用,我使用缓存作为后备:

    // 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-wrapper的特定解决方案的full code . 随意使用它!

  • 3

    如果您正在讨论表单数据,那么您可以截取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... )
          }
    })
    

相关问题