了解web Worker实现多线程工作

概述

   

     Js是单线程的,也就是任务得一件件的按照顺序处理,前面的任务没有处理完成,后面的只能等着。但是随着科技的发展,现在的计算机都是多核的CPU,单线程无法发挥计算机的能力。

    Web Worker 的作用就是在js主线程上创建一个辅助线程(Worker线程),将一些任务分配给Worker线程运行。两个线程互不干扰,也能相互通信。用户在主线程上进行UI交互时,不会卡顿和阻塞。Worker 线程也不会因为主线程交互而被打断。这个和之前的Service Worker很类似

    注意,Worker 线程比较耗费资源,不应该过度使用,任务完成后要关闭。同时,Web Worker 有以下几个使用注意点:

  • 同源限制,执行Worker线程的脚步文件必须和主线程在一个host下

  • DOM限制,Worker线程不能操作document,window,parent等对象,但可以操作navigator和location对象

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

  • 引用路径,Worker 线程引用文件时,必须是同源下的相对或者绝对路径。

  • 上下文环境,Worker线程和主线程不在同一个上下文环境,他们之间通过xx.postMessage相互通信。

  • 通信数据独立,主线程和Worker线程传递的数据都是独立的,通信的数据都是先转字符串再还原的过程,所以不用担心对象深拷贝的问题

用法

主线程

1、在主线程上新建worker线程

var worker = new Worker('./work.js');

    构造函数Worker引用的脚步文件work.js就是Worker线程的执行任务。如果构造函数Worker引用的参数路径不对,Worker会默认失败,Worker线程将不执行。

2、主线程给Woker线程发消息

worker.postMessage('Hello World');
worker.postMessage({method: 'echo', args: ['Work']});

    主线程通过实例对象worker的postMessage向Worker发消息。postMessage的参数可以是任意类型。

3、主线程监听Woker线程发消息

worker.onmessage = function (event) {
  console.log('Received message ' + event.data);
  doSomething();
}
function doSomething() {
  // 执行任务
  worker.postMessage('Work done!');
}

    主线程通过调用实例onmessage方法监听Worker线程发来的消息(event.data)

4、主线程关闭Woker线程

worker.terminate();

Worker线程

1、Worker线程监听主线程消息

self.addEventListener('message', function (e) {
  self.postMessage('You said: ' + e.data);
}, false);

    self代表Woker线程的全局对象,等同下面两种写法:

// 写法一
this.addEventListener('message', function (e) {
  this.postMessage('You said: ' + e.data);
}, false);

// 写法二
addEventListener('message', function (e) {
  postMessage('You said: ' + e.data);
}, false);

2、Worker线程给主线程发送消息

self.addEventListener('message', function (e) {
  var data = e.data;
  switch (data.cmd) {
    case 'start':
      self.postMessage('WORKER STARTED: ' + data.msg);
      break;
    case 'stop':
      self.postMessage('WORKER STOPPED: ' + data.msg);
      self.close(); // Terminates the worker.
      break;
    default:
      self.postMessage('Unknown command: ' + data.msg);
  };
}, false);

    和主线程方法一样,通过调用Worker线程的postMessage向主线程发送消息,参数就是发送的数据

3、Worker线程关闭自身

self.close();

拓展

1、可以在同一个文件里编写主线程和worker线程。

<!DOCTYPE html>
  <body>
  //worker线程的脚本
    <script id="worker" type="app/worker">
      addEventListener('message', function () {
        postMessage('some message');
      }, false);
    </script>
    //主线程脚本
    <script>
        var blob = new Blob([document.querySelector('#worker').textContent]);
            var url = window.URL.createObjectURL(blob);
            var worker = new Worker(url);
            worker.onmessage = function (e) {
              // e.data === 'some message'
            };
    </script>
  </body>
</html>

    上面代码中,先将嵌入网页的脚本代码,转成一个二进制对象,然后为这个二进制对象生成 URL,再让 Worker 加载这个 URL。这样就做到了,主线程和 Worker 的代码都在同一个网页上面。

API

Worker()

var myWorker = new Worker(jsUrl, options);

    主线程全局对象提供了Worker构造函数,它接收两个参数,第一个参数是脚本文件的的同源网址,该参数必须的,否则会报错;第二个参数是可选的配置对象,它的主要作用是指定Worke线程的名称,用来区分多个Worker线程。

// 主线程

var myWorker = new Worker('worker.js', { name : 'myWorker' });

// Worker 线程

self.name // myWorker

Worker()创建的实例对象,提供了以下属性和方法:

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

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

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

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

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

Web Worker 有自己的全局对象,不是主线程的window,而是一个专门为 Worker 定制的全局对象。因此定义在window上面的对象和方法不是全部都可以使用。

Worker 线程有一些自己的全局属性和方法。

  • self.name: Worker 的名字。该属性只读,由构造函数指定。

  • self.onmessage:指定message事件的监听函数。

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

  • self.close():关闭 Worker 线程。

  • self.postMessage():向产生这个 Worker 线程发送消息。

  • self.importScripts():加载 JS 脚本。

兼容性

文章和自己个人网站同步:

前端中台化,把格局做大——NodeJS 和测试服务探索_我叫火柴-个人博客命中注定的缘分 —— 当 NodeJS 遇见端到端测试困局,nodeJS 实现端到端服务 —— 想说爱你不容易,融入社区,反推框架的进步和完善,前端和中台化 打通基于 Cypress 的 NodeJS 服务任督二脉https://www.gcb1988.cn/article/1988_055.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值