第一次了解到Web Worker的概念还是在腾讯IVWEB团队的文章中。今天又在《高性能JavaScript》中读到,于是打算再记录一下。共同学习!
1. 前言
起初,在浏览器的UI线程之外无法运行代码。但是Web Worker
改变了这种状况,它引入了一个接口,能使代码运行且不占用浏览器UI线程的时间。作为HTML5最初的一部分,Web Worker
已经被分离出去成为独立的规范。
2. Worker
简介
每个新的Worker都在自己的线程中运行代码。这意味着Worker运行代码不进不会影响浏览器UI,也不会影响其他Worker
运行的代码。
2.1 Worker
需要注意什么?
-
Web Worker
没有绑定UI线程,这也意味着它们不能访问浏览器的许多资源。JavaScript和UI共享同一进程的部分原因是它们之间互相访问频繁,因此这些任务失控对用户体验会是一个灾难。 -
Web Worker
从外部线程种修改DOM会导致用户界面出现错误,但是每个Worker
都有自己的全局运行环境,其功能只是JavaScript特性的一个子集。
2.2 Worker
运行环境组成:
-
一个
navigator
对象,只包括四个属性:appName
、appVersion
、userAgent
和platform
。 -
一个
location
对象(与window.location相同,不过所有属性都是只读的)。 -
一个self对象,指向全局
Worker
。 -
一个
importScripts()
方法,用来加载Worker
所用到的外部JavaScript文件。 -
所有的
ECMAScript
对象,诸如:Object、Array、Date等。 -
XMLHttpRequest
构造器。 -
setTimeout()
和setInterval()
方法。 -
一个
close()
方法,它能立刻停止Worker
运行。
由于
Web Worker
有着不同的全局运行环境,因此你无法从JavaScript代码中创建它。事实上,你需要创建一个完全独立的JavaScript文件,其中包含了需要在Worker
中运行的代码。要创建Worker
线程,必须传入这个JavaScript文件的URL,例如:let worker = new Worker('workerCode.js');
*此代码一旦执行,将为这个文件创建一个新的线程和一个新的
Worker
运行环境。该文件会被异步下载,直到文件下载并执行完成后才会启动此Worker
。
3. 与Worker
通信
网页代码可以通过postMessage()
方法给Worker
传递数据,它接收一个参数,即需要传递给Worker
的数据。此外,Worker
还有一个用来接收信息的onmessage
时间处理器。例如:
let worker = new Worker('workerCode.js');
woeker.onmessage = function (event) {
alert(event.data);
}
worker.postMessage('Li');
复制代码
Worker
通过出发message
事件来接收数据。定义onmessage
事件处理器后,该事件对象就具有一个data
属性用于存放传入的数据。Worker
可通过它自己的postMessage()
方法把信息回传给页面:
// workerCode.js文件
self.onmessage = function (event) {
self.postMessage(event.data + 'is a student.');
}
复制代码
*最终的字符串在
Worker
的onmessage
事件处理器中构造完成,消息系统是网页和Worker
通信的唯一途径。
4. Worker
加载外部文件
Worker
通过importScripts()
方法加载外部JavaScript文件,该方法接收一个或多个JavaScript文件URL作为参数。importScripts()
的调用过程是阻塞式的,直到所有文件加载并执行完成之后,脚本才会继续运行。由于Worker
在UI线程之外运行,所以这种阻塞并不会影响UI相应。例如:
// workerCode.js文件
importScripts('importFile1.js', 'importFile2.js');
self.onmessage = function (event) {
self.postMessage('Hello' + event.data + '!');
}
复制代码
这段代码第一行中引入了两个JavaScript文件,它们将在Worker
线程的上下文中用到。
5. Worker
实际应用
Worker
适用于那些处理纯数据,或者与浏览器UI无关的长时间运行脚本。比如:
- 编码/解码大字符串。
- 复杂数学运算(包括图像或视频处理)。
- 大数组排序。
任何超过100ms的处理过程,都应当考虑Worker
方案是不是比基于定时器方案更为合适。比如:
解析一个很大的JSON字符串。假设数据量足够大,至少需要500ms才能完成解析。很明显时间太长了,超出了客户端允许JavaScript运行的时间,因为它会干扰用户体验。而此任务难以分解成若干个使用定时器的小任务,因此
Worker
成为最理想的解决方案。当然
Web Worker
肯定还有更多其它用处,发挥它更强的作用。
如果有什么错误请各位指出,感谢!