我在最近的一个带有 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-wrapper 的特定解决方案的完整代码。随意使用它!