HTML5的时代来到了,由于前端负责的数据处理越来越大,单单靠一个JS的单线程越来越力不从心,webWorker的出现能更好的解决该问题,这篇文章将讲述webWorker的使用。
简单的实例
使用webWorker我们可以将一些大量计算的事情放置在另一个线程进行处理,这时候我们页面不会被卡死,让网页使用流畅。
比如我们进行一个50亿次的加法计算。
1 |
|

在我的电脑上是2秒多,但一般的电脑可能要慢很多,但是作为页面展示如果需要2秒的时间那么用户体验将是相当不好的,因为两秒种的时间用户都无法操作。
这时候一般只能使用 setTimeout
将计算拆除,或者请求服务器处理,但是都很麻烦,在这里我们使用 Worker
就可以了。
script of html
1 |
|
worker-5x10^9.js
1 |
|


使用webWorker可以避免大量的计算导致的拥塞,避免页面假死,充分利用客户端的物理资源。
下面我们来详细讲述如何使用 webWorker
。
Worker简介
兼容性
虽然作为HTM5的新特性,但是各大浏览器对 webWorker
的支持都是很好的,所以我们基本可以大胆的尝试在工程中使用。

构造函数
webWorker
在浏览器中的构造函数为 Worker()
但是必须传入一个字符串参数作为 webWorker
运行的内容,在上面的示例中便是传入了 worker-5x10^9.js
来让其执行。
语法
new Worker(aURL);
参数
参数名 | 参数类型 | 参数描述 | 是否必要 |
---|---|---|---|
aURL | String | webWorker运行脚本的地址,它必须遵循同源策略 | TRUE |
用法
1 |
|
实例API
我们可以看看输出worker实例对象。

我们可以看到它主要包含4个方法:
- onerror
- onmessage
- postMessage
- terminate
十分简单
onerror
这个方法是在Worker的error事件触发时执行,需要给onerror赋值一个函数,并且会给该函数传递一个事件对象。
script of html
1 |
|
worker-error.js
1 |
|

这样我们就可以获取到内部的错误信息,并加以处理,但是一般对这方面的需求很少,主要获取内部运行的情况。
onmessage
这个方法是在Worker的内部执行 postMessage
事件触发时执行,需要给onmessage赋值一个函数,并且会给该函数传递一个事件对象。传递的值通过事件对象的 data
属性获取。
script of html
1 |
|
worker-postMessage.js
1 |
|

这样我们就可以获取到内部的发出信息。
postMessage(aMessage, transferList)
这个方法是向Worker的内部发送消息,在这里不止是传递字符串,可以传递对象等,但是不能传递函数包含的对象。
他会对对象进行深度克隆,所以可以用来进行对象的异步的深度克隆。这一部分在下面进行详细阐述。
参数名 | 参数类型 | 参数描述 | 是否必要 |
---|---|---|---|
aMessage | any | 需要发送的消息,可以传递对象,会对对象(可以包含js的内置对象类型)进行深度克隆,但是不支持函数的传递 | FALSE |
transferList | array | 将对象的上下文环境移交给worker | FALSE |
script of html
1 |
|
worker-postMessage.js
1 |
|

由于执行是异步的,所以还是要主线程的JS执行完毕后才能执行对事件的响应,第一个错误是因为对有函数的对象解析导致的,所以我们只能看到前面两个的字付串输出。
terminate()
这个函数是立刻停止worker的运行,不会等待worker的运行完成。
script of html
1 |
|

我们可以看到这里只有 123
输出,虽然依然可以向worker发送消息,但是没什么卵用。
webWorker内部环境
worker的执行的环境和浏览器环境的有一些不同,浏览器内全局变量是 window
而 worker内部是DedicatedWorkerGlobalScope
在这个环境中无法使用window来获取全局变量
script of html
1 |
|
worker-window.js
1 |
|

我们可以看到window是没有定义的,想要获取我们需要使用 self
worker-self.js
1 |
|

这样我们就可以获取内部的全局变量了,其实self在浏览器环境下也是指向全局环境的。
全局环境
worker的内部环境当然也和浏览器下的环境差不多,都含有相关的全局方法。
console
worker的内部环境也是支持console.log来方便调试的,并且它的输出会展示在浏览器的控制台当中
worker-self.js
1 |
|

对AJAX和webSocket的支持
1 |
|
这两个对象都是支持的,所以webWorker,可以负责数据请求的收发。
无法操作DOM
1 |
|
worker内部是无法操作DOM的,主要是为了线程安全,但是我们在采用VDOM的时候,便可以放入worker内部处理VDOM。
postMessage
在worker的postMessage方法,已经worker内部的postMessage都是支持对象传递的,它可以传递满足The structured clone algorithm | 结构化克隆算法的对象。
script of html
1 |
|
worker-transferList.js
1 |
|
同时在深复制的时候还保持了内部的索引结构。
transferList
最难弄清的其实是 postMessage
的 transferList
参数。
transferList数组类型
transferList数组类型必须为 ArrayBuffer
, MessagePort
and ImageBitmap
1 |
|
我们设置成 ArrayBuffer
1 |
|
我们可以看到post成功了,但同时我们会发现bufArr.byteLength的长度改变了,因为byteLength的上下文已经搬移到worker内部了。
script of html
1 |
|
worker-transferList.js
1 |
|

Worker 和 SharedWorker
上述讲述的都是页面独享 Worker
也叫 DedicatedWorker
,然而还有一个 SharedWorker
。
DedicatedWorker
会在页面关闭时随之关闭,而 SharedWorker
会在所有关联的页面都关闭后才关闭。
shared.js
1 |
|
worker-shared.js
1 |
|
当我们只在第一个页面进行刷新时,输出的都是0,但当有两个页面时,刷新一个页面输出的内容就不再只是0。
当只有一个页面时

当有两个页面时

注意
- 我也不知道为何,直接写在HTML中的sharedWorker并不会执行。
总结
这里 webWorker
简单的介绍就算完了,使用 webWorker
能减少页面的拥塞,充分利用客户的物理资源处理大量数据同时还可以用于封装接口层,毕竟是支持AJAX和webSocket的~~~。
参考资料
END
2017-03-16 完成
2017-02-25 立项