浅尝Web Worker

Worker

创建一个worker对象,可以在浏览器中创建一个新线程不阻塞UI线程渲染。

  • 必须遵守同源策略
  • 深拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<button id="btn">send msg</button>
<input type="text" id="msg">
<div><button id="terminate" style="color: red;">terminate</button></div>
<script>
const btn = document.querySelector('#btn');
const terminate = document.querySelector('#terminate')
const input = document.querySelector('#msg');
const worker = new Worker('./worker.js')
worker.onmessage = (e) => {
console.log('我接收到了',e.data);
}
btn.addEventListener('click', () => {
console.log('我发送了',input.value)
worker.postMessage(input.value);
})

terminate.addEventListener('click', () => {
worker.terminate()
})
</script>
</body>

worker.js

1
2
3
4
5
6
7
8
9
10
11
onmessage = function(e) {
console.log('另一个线程监听到了:', e.data)
postMessage('另一个线程加工了'+e.data)
}
onerror = function(e) {
console.log('onerror监听到:', e)
}
onmessageerror = function(e) {
console.log('onmessageerror监听到:',e)
}
// console.log(self);

通过new Worker(‘./worker.js’) 的worker.js 文件处于 DedicatedWorkerGlobalSpace作用域下,可以用 self 访问到这个全局对象。

所以以上三个方法就是对全局对象的事件处理函数的重写

Shared Worker

  • 必须遵守同源策略
  • 实现标签页共享
  • 深拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
const btn = document.querySelector('#btn');
const terminate = document.querySelector('#terminate')
const msg = document.querySelector('#msg');
const ul = document.querySelector('.recv')
const worker = new SharedWorker('./sharedWorker.js')
// worker.port.start();
btn.onclick = () => {
console.log('我发送了', msg.value);
worker.port.postMessage(msg.value);
}
worker.port.onmessage = function (e) {
console.log('我接收到了', e.data)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let counter = 0; // 计时器
const clients = [] //连接上的用户,注意 无论有几个标签页,e.ports 的长度始终都是1
self.onconnect = (e) => {
const port = e.ports[0];
//console.log(e.ports); //⭐这里的内容必须在 edge://inspect/#workers 的inspect 里的控制台查看
//port.postMessage('sharedworker已连接'); //不能发送e或者 ports 里的任何对象。因为他们is not transferred
console.log('sharedworker已连接')
clients.push(port);
port.onmessage = (e) => {
console.log('sharedworker接收到', e.data)
counter++;
clients.forEach(client => {
client.postMessage(counter)
})
}
};

注意

  1. 同一个name下,且同一个域名下才可以共享
  2. 想实现广播功能要自己保存每个连接(类似websocket)