server workers

全部相关demo

service worker

Service workers 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理

  • 运行在worker上下文,不能访问DOM

  • 运行在其他线程中,所以不会造成阻塞

  • 它设计为完全异步,同步API(XHR和localStorage)不能在service worker中使用

  • Service workers只能由HTTPS承载

  • workers 支持当操作出错时终止操作

  • Service workers大量使用Promise

使用 service worker 实现页面通信和监控

window.open

用于打开一个新的浏览器窗口或查找一个已命名的窗口

window.open(URL,name,specs,replace)

  • URL 可选。打开指定的页面的URL。如果没有指定URL,打开一个新的空白窗口

  • name 可选。指定target属性或窗口的名称; (默认)_blank - URL加载到一个新的窗口; name - 窗口名称; 等等

  • specs 可选。一个逗号分隔的项目列表

  • replace true 替换浏览历史中的当前条目;false 在浏览历史中创建新的条目

通过hash值或localStore实现页面通信

onbeforeunload 方法是关闭页面可以触发

a.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<html>
<head>
</head>
<body>
<div>A 页面</div>
<button onclick="toB()">B 页面</button>
<script>
// 通过hash值实现页面通信
window.addEventListener('hashchange', function () {
alert(window.location.hash);
}, false);

// 通过localStore传值
window.addEventListener('storage', function (e) {
alert(e.newValue);
});

window.name = 'a';

function toB() {
// 打开新页面并设置页面名
window.open('b.html', 'b');
}
</script>
</body>
</html>

b.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<head>
</head>
<body>
<div>这是 B crash 页面</div>
<button onclick='handleCrash()'>点击我使页面崩溃</button>
<script>
// 通过hash实现页面通信, 关闭页面前的事件监听
window.onbeforeunload = function () {
// url 传值
window.open('a.html#close', 'a');
// localStore 传值
localStorage.setItem('someParam',JSON.stringify({a: 'hello', b: 'world'}));
// chrome 和 firfox 不支持文本修改
return '确定离开此页吗?';
}
</script>
</body>
</html>

页面意外崩溃时页面通信

b 页面在加载时,设定一个状态, 正常关闭时设定一个状态,当在此打开 b 页面时,判断该状态来识别上次是正常关闭还是崩溃,然后通知 a 页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var someDataNeedTransmit = '一些需要传递的数据'
window.onload = function () {
// 页面每次挂在记录运行状态
sessionStorage.setItem('running', 'normal');
// 设置心跳, 记录崩溃前的时间
setInterval(function () {
sessionStorage.setItem('timeBeforeCrash', new Date().toString());
// 崩溃前的一些数据
sessionStorage.setItem('dataBeforeCrash', someDataNeedTransmit);
}, 1000);
}

window.onbeforeunload = function () {
// 页面每次正常关闭,调整状态
sessionStorage.setItem('running', 'exit');
return '确定离开此页吗?';
}

// 在此打开b页面时判断b上次是否正常关闭,如果不正常,则通知给a页面
if(sessionStorage.getItem('running') && sessionStorage.getItem('running') !== 'exit') {
//
}

使用 Service Worker

b.html 会崩溃的页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<html>
<head>
</head>
<body>
<div>b页面</div>
<button onclick='crash()'>点击页面崩溃</button>
<script>

function crash() {
while (true) {}
}

// service worker 实现崩溃监控 ===================
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js', {
scope: './'
}).then(function (registration) {
if (navigator.serviceWorker.controller !== null) {
// 每五秒发一次心跳
let time = 5 * 1000;
let heartbeat = function () {
console.log('心跳频率');
navigator.serviceWorker.controller.postMessage({
type: 'running',
data: {}
});
}
window.addEventListener('beforeunload', function () {
navigator.serviceWorker.controller.postMessage({
type: 'clear'
});
});
setInterval(heartbeat, time);
}
})
.catch(function (error) {
});
}
</script>
</body>
</html>

Service Worker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 每 6s 检查一次
const checkTime = 6 * 1000;

// 超过15s没有心跳则认为已经 crash
const crashTime = 15 * 1000;
let timer
let time

this.onmessage = (e) => {
const data = e.data;
// 正常心跳,检测崩溃
if (data.type === 'running') {
time = Date.now();
if (!timer) {
timer = setInterval(function () {
const now = Date.now();
if ((now - time) > crashTime) {
console.log('页面崩溃啦');
clearInterval(timer);
timer = null;
} else {
console.log('页面还很正常');
}
}, checkTime)
}
}
}

Service Worker 会经历下载, 安装, 激活过程,所以代码不会立即生效,可稍作等待, 利用web-workder可同样实现

workers可用函数和接口

  • Navigator

  • XMLHttpRequest

  • Array, Date, Math, String

  • WindowTimers.setTimeout, WindowTimers.setInterval

Service Worker实现缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw-demo-cache.js');
}
sw-demo-cache.js这个JS中复制如下代码:
var VERSION = 'v1';

// 缓存
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(VERSION).then(function(cache) {
return cache.addAll([
'./start.html',
'./static/jquery.min.js',
'./static/mm1.jpg'
]);
})
);
});

// 缓存更新
self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
// 如果当前版本和缓存版本不一致
if (cacheName !== VERSION) {
return caches.delete(cacheName);
}
})
);
})
);
});

// 捕获请求并返回缓存数据
self.addEventListener('fetch', function(event) {
event.respondWith(caches.match(event.request).catch(function() {
return fetch(event.request);
}).then(function(response) {
caches.open(VERSION).then(function(cache) {
cache.put(event.request, response);
});
return response.clone();
}).catch(function() {
return caches.match('./static/mm1.jpg');
}));
});

把cache.addAll()方法中缓存文件数组换成你希望缓存的文件数组。
恭喜你,简单3步曲,复制、粘贴、改路径。你的网站已经支持Service Worker缓存,甚至离线也可以自如访问,支持各种网站,PC和Mobile通杀,不支持的浏览器没有任何影响,支持的浏览器天然离线支持,想要更新缓存,v1换成v2就可以,so easy!。

server worker

返回
顶部