worker 多线程

368 阅读2分钟

worker使用场景

js是单线程运行的,在遇到一些需要处理大量数据的js时,可能会阻塞页面的加载,造成页面的假死。这时我们可以使用worker来开辟一个独立于主线程的子线程来进行哪些大量运算。这样就不会造成页面卡死。也说明 worker可以用来解决大量运算是造成页面卡死的问题。

worker语法

const worker=new Worker(aURL, options)

它有两个参数:

aURL(必须)是一个DOMString 表示worker 将执行的脚本的URL。它必须遵守同源策略。

options (可选)它的一个作用就是指定 Worker 的名称,用来区分多个 Worker 线程

worker的属性

Worker.onerror:指定 error 事件的监听函数

Worker.onmessage:指定 message 事件的监听函数,发送过来的数据在Event.data属性中。

Worker.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。

worker的方法

Worker.postMessage():向 Worker 线程发送消息。

Worker.terminate():立即终止 Worker 线程。

使用worker的注意点

1.同源限制 分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

2.DOM 限制 Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。

3.通信联系 Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。

4.脚本限制 Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。

5.文件限制 Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

实现将worker主线程与子线程代码放在同一个文件中

通常情况下,Worker 载入的是一个单独的 JavaScript 脚本文件,但是也可以载入与主线程在同一个网页的代码。

<script id="worker" type="app/worker"> //*type要指明一个浏览器不认识的类型
        self.onmessage = function (event) { //子线程接收主线程传递数据触发的方法
            var data = event.data; 
            var ans = fibonacci(data); 
            this.postMessage(ans); //向主线程提交请求完成后或处理后的数据
        };
        function fibonacci(n) { //子线程要执行的方法,一般是请求大量数据,这里是一个递归方法
              return n < 2 ? n : arguments.callee(n - 1) + arguments.callee(n - 2);
        }
</script>
<script>
    var blob = new Blob([document.querySelector('#worker').textContent]);// 转码
    var url = window.URL.createObjectURL(blob);  // 编译为url
    var worker = new Worker(url); //因为worker只能请求网络数据.所以需要编译为url
    worker.postMessage(40);//向子线程传数据
    worker.onmessage=function(event){ // 接收子线程传递的数据
        var data=event.data;
        console.log(data) //打印
    };
    worker.onerror=function(event){ // 遇到错误时触发 ,打印错误信息查看
        console.log(event.fileName,event.lineo,event.message);
    };
</script>

self代表子线程,即子线程的全局对象,因为在不同的上下文中,也可以使用this指代

上面是一段嵌入网页的脚本,注意必须指定<script>标签的type属性是一个浏览器不认识的值,上例是app/worker,先将嵌入网页的脚本代码,转成一个二进制对象,然后为这个二进制对象生成 URL,再让 Worker 加载这个 URL。这样就做到了,主线程和 Worker 的代码都在同一个网页上面。

参考

MDN

Web Worker 使用教程