WebWorker
简介
众所周知,javascript是一个单线程的环境。而WebSorker的出现就是为其创建多线程环境。使用它创建的子线程只会在后台运行,不会阻塞到主线程。等到子线程完成任务后再把结果返回给主线程。这样做就不会阻塞到主线程的运行。但是Worker比较耗费资源,不应该被过度使用,使用完毕后应该主动关闭。
使用场景
- 高延迟的任务(传大内存的文件等)
- 长时间的计算 ...
使用注意点
- 同源限制 分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
- DOM 限制 Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
- 通信联系 Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
- 脚本限制 Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
- 文件限制
Worker 线程无法读取本地文件,即不能打开本机的文件系统file://.,它所加载的脚本,必须来自网络。
使用
- 创建WebWorker 参数为需要执行的脚本,因为不能读取本地文件,所以这个地址必须来自网络。如果下载失败(404),Worker就会默默失败
const worker = new Worker('http://127.0.0.1:5500/js/work.js'); //* 该脚本内的js代码会被执行
work.js
console.log('hello work')
- 线程通信
主要通信方法为两个,onmessage为监听消息,postMessage为发送消息
子组件通过全局this属性来进行发送和api调用
postMessage可传多种类型 file object... 传向子组件的内容会进行序列化。即子线程修改父线程传过来的值 不会影响到父线程
const worker = new Worker('http://127.0.0.1:5500/js/work.js'); //* 该脚本内的js代码会被执行
//* 信息通信
worker.onmessage = function(event) {
console.log('worker message', event.data);
//* postMessage可传多种类型 file object... 传向子组件的内容会进行序列化。即子线程修改父线程传过来的值 不会影响到父线程
worker.postMessage('Work done!')
}
work.js
const self = this
//* 发送给父线程消息
self.postMessage('parane!!!')
self.onmessage = function(event) {
console.log('parent message on -> ', event.data)
}
- 父线程监听子线程的错误
const worker = new Worker('http://127.0.0.1:5500/js/work.js');
worker.onerror = function(error) {
console.log('worker error ->', error)
}
work.js
throw new Error('work error!!!')
- 关闭webworker线程 分为两部分 1.父线程关闭子线程 2.子线程自己关闭
const worker = new Worker('http://127.0.0.1:5500/js/work.js');
worker.terminate()
work.js
const self = this
self.close()
- 调用页面内的WebWorker 有时候我们不想写js文件。想直接在html中调用 使用下方的方法
<script id="worker" type="app/worker">
const self = this;
self.onmessage = function(event) {
console.log('script worker ->', event.data)
self.postMessage('hi, parant. from script')
}
</script>
<script>
//* 引用同页面下的webworker
var blob = new Blob([document.querySelector('#worker').textContent]);
var url = window.URL.createObjectURL(blob);
var scriptWorker = new Worker(url);
scriptWorker.onmessage = function (e) {
console.log('worker script ->', e.data)
};
scriptWorker.postMessage(' script worker')
</script>
API
- 主线程
var myWorker = new Worker(jsUrl, options);
Worker()构造函数,可以接受两个参数。第一个参数是脚本的网址(必须遵守同源政策),该参数是必需的,且只能加载 JS 脚本,否则会报错。第二个参数是配置对象,该对象可选。它的一个作用就是指定 Worker 的名称,用来区分多个 Worker 线程。
// 主线程
var myWorker = new Worker('worker.js', { name : 'myWorker' });
// Worker 线程
self.name // myWorker
API
Worker.onerror:指定 error 事件的监听函数。
Worker.onmessage:指定 message 事件的监听函数,发送过来的数据在Event.data属性中。
Worker.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
Worker.postMessage():向 Worker 线程发送消息。
Worker.terminate():立即终止 Worker 线程。
- Worker线程
self.name: Worker 的名字。该属性只读,由构造函数指定。
self.onmessage:指定message事件的监听函数。
self.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
self.close():关闭 Worker 线程。
self.postMessage():向产生这个 Worker 线程发送消息。
self.importScripts():加载 JS 脚本。