js系列-web worker

496 阅读2分钟

 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 实现的