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作为参数。它的调用过程是阻塞式的,直到所有文件成功加载并执行后才会继续运行后续其它代码。