具有多个缓存的 Service Worker
Service Worker with Multiple Caches
有许多示例可用于使用类似于以下内容的单个缓存来初始化 Service Worker:
let cacheName = 'myCacheName-v1';
let urlsToCache = ['url1', 'url2', url3'];
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open(cacheName).then(function (cache) {
return cache.addAll(urlsToCache);
}).then(function () {
return this.skipWaiting();
})
);
});
我希望在我的 service worker 上初始化多个缓存。动机是根据资产的变化趋势对资产进行分组(例如,静态应用程序数据与 css、javascript 等)。使用多个缓存,我可以更新单个缓存(通过版本化的缓存名称)作为缓存中的文件更改。理想情况下,我希望设置类似于以下的结构:
let appCaches = [{
name: 'core-00001',
urls: [
'./',
'./index.html', etc...
]
},
{
name: 'data-00001',
urls: [
'./data1.json',
'./data2.json', etc...
]
},
etc...
];
到目前为止我最好的尝试是类似于:
self.addEventListener('install', function (event) {
appCaches.forEach(function (appCache) {
event.waitUntil(
caches.open(appCache.name).then(function (cache) {
return cache.addAll(appCache.urls);
}));
});
self.skipWaiting();
});
这种方法似乎有效。但是,我仍然是 service worker 和 promises 的新手。有些东西告诉我,这种方法有一个陷阱,我太缺乏经验而无法识别。有没有更好的方法来实现这个?
最好只在一个处理程序中调用 event.waitUntil
一次,但好处是它相对容易等待一个 Promise。
类似的东西应该可以工作:
event.waitUntil(Promise.all(
myCaches.map(function (myCache) {
return caches.open(myCache.name).then(function (cache) {
return cache.addAll(myCache.urls);
})
)
));
Promise.all
采用 Promise 数组并仅在数组中的所有 promise 解析后解析,这意味着 install
处理程序将等待所有缓存初始化。
感谢 pirxpilot! Your answer, combined with JavaScript Promises: an Introduction,经过大量试验和错误找出如何将所有这些 Promise 链接在一起的结果是一个不错的小实现。
我添加了仅缓存更改的要求。根据最佳实践,旧缓存会在 'activate' 事件期间被删除。最终产品是:
let cacheNames = appCaches.map((cache) => cache.name);
self.addEventListener('install', function (event) {
event.waitUntil(caches.keys().then(function (keys) {
return Promise.all(appCaches.map(function (appCache) {
if (keys.indexOf(appCache.name) === -1) {
return caches.open(appCache.name).then(function (cache) {
console.log(`caching ${appCache.name}`);
return cache.addAll(appCache.urls);
})
} else {
console.log(`found ${appCache.name}`);
return Promise.resolve(true);
}
})).then(function () {
return this.skipWaiting();
});
}));
});
self.addEventListener('activate', function (event) {
event.waitUntil(
caches.keys().then(function (keys) {
return Promise.all(keys.map(function (key) {
if (cacheNames.indexOf(key) === -1) {
console.log(`deleting ${key}`);
return caches.delete(key);
}
}));
})
);
});
有许多示例可用于使用类似于以下内容的单个缓存来初始化 Service Worker:
let cacheName = 'myCacheName-v1';
let urlsToCache = ['url1', 'url2', url3'];
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open(cacheName).then(function (cache) {
return cache.addAll(urlsToCache);
}).then(function () {
return this.skipWaiting();
})
);
});
我希望在我的 service worker 上初始化多个缓存。动机是根据资产的变化趋势对资产进行分组(例如,静态应用程序数据与 css、javascript 等)。使用多个缓存,我可以更新单个缓存(通过版本化的缓存名称)作为缓存中的文件更改。理想情况下,我希望设置类似于以下的结构:
let appCaches = [{
name: 'core-00001',
urls: [
'./',
'./index.html', etc...
]
},
{
name: 'data-00001',
urls: [
'./data1.json',
'./data2.json', etc...
]
},
etc...
];
到目前为止我最好的尝试是类似于:
self.addEventListener('install', function (event) {
appCaches.forEach(function (appCache) {
event.waitUntil(
caches.open(appCache.name).then(function (cache) {
return cache.addAll(appCache.urls);
}));
});
self.skipWaiting();
});
这种方法似乎有效。但是,我仍然是 service worker 和 promises 的新手。有些东西告诉我,这种方法有一个陷阱,我太缺乏经验而无法识别。有没有更好的方法来实现这个?
最好只在一个处理程序中调用 event.waitUntil
一次,但好处是它相对容易等待一个 Promise。
类似的东西应该可以工作:
event.waitUntil(Promise.all(
myCaches.map(function (myCache) {
return caches.open(myCache.name).then(function (cache) {
return cache.addAll(myCache.urls);
})
)
));
Promise.all
采用 Promise 数组并仅在数组中的所有 promise 解析后解析,这意味着 install
处理程序将等待所有缓存初始化。
感谢 pirxpilot! Your answer, combined with JavaScript Promises: an Introduction,经过大量试验和错误找出如何将所有这些 Promise 链接在一起的结果是一个不错的小实现。
我添加了仅缓存更改的要求。根据最佳实践,旧缓存会在 'activate' 事件期间被删除。最终产品是:
let cacheNames = appCaches.map((cache) => cache.name);
self.addEventListener('install', function (event) {
event.waitUntil(caches.keys().then(function (keys) {
return Promise.all(appCaches.map(function (appCache) {
if (keys.indexOf(appCache.name) === -1) {
return caches.open(appCache.name).then(function (cache) {
console.log(`caching ${appCache.name}`);
return cache.addAll(appCache.urls);
})
} else {
console.log(`found ${appCache.name}`);
return Promise.resolve(true);
}
})).then(function () {
return this.skipWaiting();
});
}));
});
self.addEventListener('activate', function (event) {
event.waitUntil(
caches.keys().then(function (keys) {
return Promise.all(keys.map(function (key) {
if (cacheNames.indexOf(key) === -1) {
console.log(`deleting ${key}`);
return caches.delete(key);
}
}));
})
);
});