web worker的介绍:
为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Web Worker 有以下几个使用注意点:
-
Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭
-
同源限制:分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
-
DOM 限制:Worker 无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
-
通信联系:web worker和主线程之间通过postMessage进行通信
-
脚本限制:Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
-
文件限制:Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。
Web Worker 有两个特点:
-
只能服务于新建它的页面,不同页面之间不能共享同一个 Web Worker。service worker 服务于多个页面
-
当页面关闭时,该页面新建的 Web Worker 也会随之关闭,不会常驻在浏览器中。service worker的生命周期就比 web worker长,在页面关闭之后还会存在。
基本用法:
在主线程中:
<script type="text/javascript">
const worker = new Worker('./worker.js’); // 直接使用new Worker生成实例
worker.postMessage('Hello World');
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
doSomething();
}
function doSomething() {
// 执行任务
worker.postMessage('Work done!');
worker.terminate();
}
</script>
在worker.js 文件中:
// 写法一
this.addEventListener('message', function (e) {
this.postMessage('You said: ' + e.data);
}, false);
// 写法二
self.addEventListener('message', function (e) {
postMessage('You said: ' + e.data);
}, false);
可以使用 self.close() 关闭自身
web worker不能加载本地的问题,所以可以这么解决:
<script id="getWorker" type="javascript/worker">
this.addEventListener('message', function (e) {
this.postMessage('我这里是worker文件' + e.data);
}, false);
</script>
<script>
let workerBlob = new Blob([document.getElementById('getWorker').textContent])
let worker = new Worker(window.URL.createObjectURL(workerBlob))
worker.postMessage('Hello World');
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
doSomething();
}
function doSomething() {
// 执行任务
worker.postMessage('Work done!');
worker.terminate();
}
</script>
web worker的一些属性和注意点:
-
importScripts():在内部加载其他脚本,也可以加载多个
importScripts('script1.js’); importScripts('script1.js', 'script2.js');
-
错误的处理:Worker 会触发主线程的error事件。
worker.onerror(function (event) { // ... }); // 或者 worker.addEventListener('error', function (event) { // ... });
-
location:location 属性返回当线程被创建出来的时候与之关联的 WorkerLocation 对象,它表示用于初始化这个工作线程的脚步资源的绝对 URL,即使页面被多次重定向后,这个 URL 资源位置也不会改变。
-
XMLHttpRequest:有了它,才能发出Ajax请求
-
setTimeout/setInterval:延时执行函数和定时执行函数,和window对象的方法相同。addEventListener/postMessage:第一个为注册监听事件,和window对象的相同,不在赘述。postMessage上面也介绍过了,是主线程和子线程之间通信的方法。
MessageChannel实现worker间通信:
不仅主线程和 Worker 线程间可以通信,不同的 Worker 之间也可以通信,可以 MessageChannel 实现的