Web Workers简介


Web Workers

因为Javascript从设计之初就是单线程的,所以它没有原生支持多线程操作。它没有办法在浏览器UI线程之外运行代码。Web Workers API改变了这种状况,它引入了一个接口,能够使代码运行且不占用浏览器UI线程的时间。作为HTML5最初的一部分,Web Workers API已经被分离出去称为独立的规范。

Web Workers给Web应用带来的潜在的巨大性能提升,因为每个Worker都在自己的线程中运行代码。这意味着Worker运行代码不仅不会影响浏览器UI,也不会影响其它Worker中运行的代码。

Worker运行环境

由于Web Workers没有绑定UI线程,这也意味着它们不能访问浏览器的许多资源。Javascript和UI共享同一线程的部分原因是它们之间互相访问频繁,因此这些任务失控回导致糟糕的用户体验。Web Workers从外部线程中修改DOM会导致用户界面出现错误。但是每个Web Worker都有自己的全局运行环境,其功能只是javascript特性的一个子集。Web Worker运行环境如下部分组成:

  • navigator对象,只包含四个属性:appName、appVersion、userAgent和platform
  • location对象,与window.location相同只是所有属性都是只读的
  • self对象,指向全局worker对象
  • importScript方法,用来加载Worker所用到的外部Javascript文件
  • 所有ECMAScript对象,如Object、Array、Date、Math等
  • XMLHttpRequest构造器
  • setTimeout和setInterval方法
  • close方法,它能够立即停止Worker运行

Web Worker有着不同的全局运行环境,因此你无法从Javascript的代码中创建它。使用它需要一个完全独立的js文件,里面包含Worker中运行代码。

var worker = new Worker("test.js");

这个代码一但执行,将为这个文件创建一个新的线程和一个新的Worker运行环境。该文件会被异步下载,直到文件被下载并执行完成后才会启动此Worker

与Worker通信

Worker与网页代码通过事件接口通信。网页代码可以使用postMessage()方法给Worker传递数据,它接受一个参数。此外Worker中有用于接收信息的onmessage事件处理器。

var worker = new Worker("test.js");
worker.onmessage = function(event){
  console.log(event.data); // hello,world
};
worker.postMessage("Asuhe");

Worker内通过触发message事件来接收数据。Worker可以通过自己的postMessage()方法来把数据传递回页面。

// test.js
self.onmessage = function(event){
  console.log(event.data); // Asuhe
  self.postMessage("hello,world");
}

这种方式是它们之间通信的唯一方式。

允许传递基本类型的数据和对象。其它类型的数据不允许被传递。

Worker加载外部文件

Worker通过importScript()方法加载外部js文件,该方法可以接受一个或多个js文件的url作为参数。它的调用过程是阻塞式的,直到所有文件成功加载并执行后才会继续运行后续其它代码。