WebWorker

368 阅读3分钟

WebWorker

简介

众所周知,javascript是一个单线程的环境。而WebSorker的出现就是为其创建多线程环境。使用它创建的子线程只会在后台运行,不会阻塞到主线程。等到子线程完成任务后再把结果返回给主线程。这样做就不会阻塞到主线程的运行。但是Worker比较耗费资源,不应该被过度使用,使用完毕后应该主动关闭。

使用场景
  • 高延迟的任务(传大内存的文件等)
  • 长时间的计算 ...
使用注意点
  1. 同源限制 分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
  2. DOM 限制 Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
  3. 通信联系 Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
  4. 脚本限制 Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
  5. 文件限制 Worker 线程无法读取本地文件,即不能打开本机的文件系统file://.,它所加载的脚本,必须来自网络。
使用
  1. 创建WebWorker 参数为需要执行的脚本,因为不能读取本地文件,所以这个地址必须来自网络。如果下载失败(404),Worker就会默默失败
const worker = new Worker('http://127.0.0.1:5500/js/work.js'); //* 该脚本内的js代码会被执行

work.js

console.log('hello work')
  1. 线程通信 主要通信方法为两个,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)
}
  1. 父线程监听子线程的错误
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!!!')
  1. 关闭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()
  1. 调用页面内的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
  1. 主线程
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 线程。
  1. Worker线程
self.name: Worker 的名字。该属性只读,由构造函数指定。
self.onmessage:指定message事件的监听函数。
self.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
self.close():关闭 Worker 线程。
self.postMessage():向产生这个 Worker 线程发送消息。
self.importScripts():加载 JS 脚本。

参考链接