Javascript 中的服务工作者
什么是服务工作者:
Service Worker 是在浏览器后台独立运行的脚本。在用户端,它可以拦截其网络请求并决定加载什么(获取)。
Service Worker 主要提供后台同步、推送通知等功能,它们通常用于“离线优先”应用程序,让开发人员有机会完全控制用户体验。
在此之前,已经有一个名为AppCache的 API,它一直在尝试提供离线体验功能。但是, AppCache API的接口出现了很多问题,Service Worker 在这里,正在解决它们。
Service Worker 生命周期:
Service Worker 的生命周期与网页完全分离。它是一个可编程的网络代理,它在不使用时终止,并在下次需要时重新启动。 Service Worker 严重依赖 Javascript Promises 的使用,因此如果您不熟悉它们,最好复习一下它们。
在安装过程中,Service Worker 可以缓存一些静态资产,例如网页。如果浏览器缓存文件成功,就会安装 service worker。
之后,需要激活worker。在激活期间,服务工作者可以管理和决定对旧缓存发生什么,通常它们会被删除并替换为新版本。
最后,激活后,Service Worker 将控制其范围内的所有页面,而最初注册 Service Worker 的页面则需要刷新。服务工作者在内存使用方面很聪明,如果没有可取的东西并且没有消息事件发生,它将被终止。
下面是浏览器和网络之间的服务工作者位置的图片。
先决条件:
- HTTPS 除非在本地主机上
- Service Worker 需要使用 HTTPS 连接。在部署之前,worker 确实在 localhost 服务器下工作,但如果要将其上传到 Internet,则需要在服务器上设置 HTTPS。托管免费演示的一个好地方是GitHub Pages ,它是基于 HTTPS 的服务器。
- 浏览器支持
- Service Worker 在 Internet 上受到Chrome 、 Firefox 、 Opera 、 Safari和Edge的高度支持,这使得它们值得部署。
登记:
要设置服务工作者,它需要注册。这是在您页面的 Javascript 中完成的。一旦注册了服务工作者,这将导致浏览器开始在后台安装它。
// Ensure that the browser supports the service worker API
if (navigator.serviceWorker) {
// Start registration process on every page load
window.addEventListener('load', () => {
navigator.serviceWorker
// The register function takes as argument
// the file path to the worker's file
.register('/service_worker.js')
// Gives us registration object
.then(reg => console.log('Service Worker Registered'))
.catch(swErr => console.log(
`Service Worker Installation Error: ${swErr}}`));
});
}
安装:
服务工作者注册后,需要安装它,这是在服务工作者文件中完成的,您通常希望在其中获取缓存资产。
需要采取以下步骤:
- 打开缓存
- 缓存资产
- 确认缓存是否成功
var cacheName = 'geeks-cache-v1';
var cacheAssets = [
'/assets/pages/offline-page.html',
'/assets/styles/offline-page.css',
'/assets/script/offline-page.js',
];
// Call install Event
self.addEventListener('install', e => {
// Wait until promise is finished
e.waitUntil(
caches.open(cacheName)
.then(cache => {
console.log(`Service Worker: Caching Files: ${cache}`);
cache.addAll(cacheAssets)
// When everything is set
.then(() => self.skipWaiting())
})
);
})
激活:
// Call Activate Event
self.addEventListener('activate', e => {
console.log('Service Worker: Activated');
// Clean up old caches by looping through all of the
// caches and deleting any old caches or caches that
// are not defined in the list
e.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(
cache => {
if (cache !== cacheName) {
console.log('Service Worker: Clearing Old Cache');
return caches.delete(cache);
}
}
)
)
})
);
})
抓取事件:
一旦设置了服务工作者,它应该开始交互并使用缓存的响应。当特定用户浏览网页时,Service Worker 开始接收fetch事件。下面的例子演示了当worker接收到一个fetch事件并搜索匹配的缓存时,如果有,则返回缓存的文件/值,否则返回调用fetch的默认响应
var cacheName = 'geeks-cache-v1';
// Call Fetch Event
self.addEventListener('fetch', e => {
console.log('Service Worker: Fetching');
e.respondWith(
fetch(e.request)
.then(res => {
// The response is a stream and in order the browser
// to consume the response and in the same time the
// cache consuming the response it needs to be
// cloned in order to have two streams.
const resClone = res.clone();
// Open cache
caches.open(cacheName)
.then(cache => {
// Add response to cache
cache.put(e.request, resClone);
});
return res;
}).catch(
err => caches.match(e.request)
.then(res => res)
)
);
});
Service Worker 不能: '
但是,Service Worker 可以:
常见用例:
参考: https://developers.google.com/web/fundamentals/primers/service-workers/