对于复杂的逻辑,可以放在另一线程,不放在主线程,这与web worker操作极其相似,但是存在一些区别
service worker | web worker |
---|---|
必须在https环境下进行工作 | 不需要 |
一旦install就一直存在 | |
用的时候直接唤醒 | 不用的时候自动睡眠 |
离线内容开发者可控 | |
可编程拦截代理请求和返回,缓存的文件可以被网页进程取到,包括离线状态 | |
不能直接操作dom不能用alert这些全局函数 | 同样 |
异步实现,内部大部分是通过promise实现 | 同样 |
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/server.js', {scope: '/'}) // 定义相关文件的位置,scope为子目录文件夹名称
.then(function (registration) {
// 注册成功
})
.catch(function (err) {
// 注册失败:
});
});
}
在 chrome://inspect/#service-workers 进行查看是否已经注册
一般是用来填充浏览器的离线缓存能力,可以存储网络发来的资源,并且根据请求来生成key,
// 监听 service worker 的 install 事件
this.addEventListener('install', function (event) {
// 如果监听到了 service worker 已经安装成功的话,就会调用 event.waitUntil 回调函数
event.waitUntil(
// 安装成功后操作 CacheStorage 缓存,使用之前需要先通过 caches.open() 打开对应缓存空间。
caches.open('my-test-cache-v1').then(function (cache) {
// 通过 cache 缓存对象的 addAll 方法添加 precache 缓存
return cache.addAll([
'/',
'/index.html',
'/main.css',
'/main.js',
'/image.jpg'
]);
})
);
});
由于localstorage是同步的做法,所以不允许在service worker上使用
每次service worker控制的资源被请求到时,就会触发fetch事件,这些包括scopr指定的所有html文档,和这个HTML引用的所有任何资源。
this.addEventListener('fetch', function (event) {
event.respondWith(
// 劫持HTTP响应
caches.match(event.request).then(function (response) {
// 如果 Service Worker 有自己的返回,就直接返回,减少一次 http 请求
if (response) {
return response;
}
// 如果 service worker 没有返回,那就得直接请求真实远程服务
var request = event.request.clone(); // 把原始请求拷过来
return fetch(request).then(function (httpRes) {
// http请求的返回已被抓到,可以处置了。
// 请求失败了,直接返回失败的结果就好了。。
if (!httpRes || httpRes.status !== 200) {
return httpRes;
}
// 请求成功的话,将请求缓存起来。
var responseClone = httpRes.clone();
caches.open('my-test-cache-v1').then(function (cache) {
cache.put(event.request, responseClone);
});
return httpRes;
});
})
);
});
// 安装阶段跳过等待,直接进入 active
self.addEventListener('install', function (event) {
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', function (event) {
event.waitUntil(
Promise.all([
// 更新客户端
self.clients.claim(),
// 清理旧版本
caches.keys().then(function (cacheList) {
return Promise.all(
cacheList.map(function (cacheName) {
if (cacheName !== 'my-test-cache-v1') {
return caches.delete(cacheName);
}
})
);
})
])
);
});
如果删除了cache上的键,但是浏览器却缓存了,那么就对这些文件设置更短的缓存期或者过滤规则
使用Registration.update()更新这个页面
var version = '1.0.1';
navigator.serviceWorker.register('/sw.js').then(function (reg) {
if (localStorage.getItem('sw_version') !== version) {
reg.update().then(function () {
localStorage.setItem('sw_version', version)
});
}
});
如果该文件已 24 小时没有更新,当 Update 触发时会强制更新。这意味着最坏情况下 Service Worker 会每天更新一次
这里我有一个问题:service worker里针对不同注册安装的文件有不同的worker,这个worker是为所有注册这个的页面服务的,那一个页面进行注册安装之后,其他的页面在注册过后,还需要安装吗,