[英]Can service workers cache POST requests?
我尝试在fetch事件中缓存服务工作者的POST请求。
我使用了cache.put(event.request, response)
,但返回的promise被TypeError: Invalid request method POST.
拒绝TypeError: Invalid request method POST.
。
当我尝试使用相同的POST API时, caches.match(event.request)
给了我undefined。
但是当我为GET方法做同样的事情时,它起作用了:对于GET请求的caches.match(event.request)
给了我一个响应。
服务工作者可以缓存POST请求吗? 如果他们不能,我们可以使用什么方法使应用程序真正脱机?
您无法使用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。
我在最近使用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的特定解决方案的完整代码 。 随意使用它!
如果您正在讨论表单数据,那么您可以截取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... )
}
})
通过使用Cloud Firestore脱机持久性,可以获得另一种提供完整脱机体验的方法。
POST / PUT请求在本地缓存数据库上执行,然后在用户恢复其Internet连接时自动同步到服务器(请注意,有500个脱机请求的限制)。
遵循此解决方案需要考虑的另一个方面是,如果多个用户具有同时进行同步的脱机更改,则无法保证更改将按照服务器上的正确时间顺序执行,因为Firestore使用先到先服务逻辑。
根据https://w3c.github.io/ServiceWorker/#cache-put (第4点)。
if(request.method !== "GET") {
return Promise.reject('no-match')
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.