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