Html5 Web Worker网页工人线程

什么是Web Worker?

web worker 是运行在后台的 JavaScript,不会影响页面的性能。

Web Worker有什么用?

JavaScript语言采用的是单线程模型,也就是说,所有任务排成一个队列,一次只能做一件事。随着电脑计算能力的增强,尤其是多核CPU的出现,这一点带来很大的不便,无法充分发挥JavaScript的潜力。
Web Worker的目的,就是为JavaScript创造多线程环境,允许主线程将一些任务分配给子线程。在主线程运行的同时,子线程在后台运行,两者互不干扰。等到子线程完成计算任务,再把结果返回给主线程。因此,每一个子线程就好像一个“工人”(worker),默默地完成自己的工作。这样做的好处是,一些高计算量或高延迟的工作,被worker线程负担了,所以主进程(通常是UI进程)就会很流畅,不会被阻塞或拖慢,可以提高应用的总体性能,并且提升用户体验。

Web Worker的特点

Web Worker有以下几个特点:

  • 同域限制。子线程加载的脚本文件,必须与主线程的脚本文件在同一个域。
  • DOM限制。子线程所在的全局对象,与主进程不一样,它无法读取网页的DOM对象,即document、window、parent这些对象,子线程都无法得到。(但是,navigator对象和location对象可以获得。)
  • 脚本限制。子线程无法读取网页的全局变量和函数,也不能执行alert和confirm方法,不过可以执行setInterval和setTimeout,以及使用XMLHttpRequest对象发出AJAX请求。
  • 文件限制。子线程无法读取本地文件,即子线程无法打开本机的文件系统,它所加载的脚本,必须来自网络。

Web Worker的兼容性

在创建 web worker 之前,请检测用户的浏览器是否支持它:

if(window.Worker){
    Yes! Web worker support!
    // Some code.....
  }else{
      Sorry! No Web Worker support..
}

IE10+及所有主流浏览器均支持 web worker。

Web Worker常用API

1.postMessage(data)
子线程与主线程之间互相通信使用方法,传递的data为任意值。
2.message
当有消息发送时,触发该事件。消息发送是双向的,消息内容可通过data来获取。
3.terminate()
主线程中终止worker,此后无法再利用其进行消息传递。注意:一旦terminate后,无法重新启用,只能另外创建。
4.error
出错处理。错误消息可以通过e.message来获取。

Web Worker实例

//file:main.js
//创建worker子线程
var worker = new Worker("worker.js");
//主线程向子线程发送内容
worker.postMessage("hello world!");
//主线程通过message事件监听子线程发来的内容
worker.onmessage = function(e) {
    console.log(e.data);
};
//主线程可以监听子线程是否发生错误。
//如果发生错误,会触发主线程的error事件。
worker.onerror(function(e) {
  console.log(e);
});
//关闭子线程
worker.terminate();

//file:worker.js
//子线程接收消息
self.onmessage = function(e){
    self.postMessage('You said: ' + e.data);
};

worker.js执行的上下文,与主页面执行时的上下文并不相同,最顶层的对象并不是window,而是WorkerGlobalScope,所以无法访问window、与window相关的DOM API,但是可以与setTimeout、setInterval等协作。
WorkerGlobalScope作用域下的常用属性、方法如下:

  1. self
      我们可以使用 WorkerGlobalScope 的 self 属性来或者这个对象本身的引用
  2. location
      location 属性返回当线程被创建出来的时候与之关联的 WorkerLocation 对象,它表示用于初始化这个工作线程的脚步资源的绝对 URL,即使页面被多次重定向后,这个 URL 资源位置也不会改变。
  3. close
      关闭当前线程,与terminate作用类似 self.close()
  4. importScripts
      我们可以通过importScripts()方法通过url在worker中加载库函数
  5. XMLHttpRequest
  6. setTimeout/setInterval以及addEventListener

详见JavaScript 标准参考教程