1.JS单线程
说起Web Workers,首先必须了解因为JS运行在浏览器中,是单线程的,每个window一个JS线程,既然是单线程的,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码。而浏览器是事件驱动的(Event driven),浏览器中很多行为是异步(Asynchronized)的,会创建事件并放入执行队列中。javascript引擎是单线程处理它的任务队列,你可以理解成就是普通函数和回调函数构成的队列。当异步事件发生时,如mouse click, a timer firing, or an XMLHttpRequest completing(鼠标点击事件发生、定时器触发事件发生、XMLHttpRequest完成回调触发等),将他们放入执行队列,等待当前代码执行完成。
2.Web Workers(多线程)
什么是Web Worker?
web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。
有什么好处?
1:子线程计算不会阻塞主线程
2:充分利用CPU!
OK,现在来具体实现多线程!
var oW = new Worker('a.js');
//a.js是子线程js文件,代表的是后台需要处理的地址
oW.postMessage(12);
//在多线程里,利用postMessage来传输数据
下面来写a.js文件。
//用onmessage事件来接收数据,ev.data代表的是接收过来的数据,这里指主线程发过来的12
self.onmessage=function(ev){
//self指全局worker对象(用this也行)
alert(ev.data)
}
这里需要注意的是上面在子线程里用alert是错误的。
安全与限制
在worker的代码中,不要访问一些重要的JavaScript对象,如document、window、console、parent,更重要的是不要访问DOM对象。也许不用DOM元素以至不能更新页面元素听上去有点严格,但是这是一个重要的安全设计决定。
想象一下,如果众多线程都试着去更新同一个元素那就是个灾难。所以,web worker需要处在一个严格的并线程安全的环境中。
正如之前所说,你可以通过worker处理数据,并将结果返回主线程,进而更新DOM元素。尽管它们不能访问一些重要的JavaScript对象,但是它们可以调用一些函数,如setTimeout()/clearTimeout()、setInterval()/clearInterval()、navigator等等,也可以访问XMLHttpRequest和localStorge对象。
为了能和服务器交互,worker必须遵守同源策略(same-origin policy)(译注:可参考国人文章同源策略)。比如,位于http://www.example.com/ 内的脚本文件不能访问https://www.example.com 的脚本。尽管域名相同,但同源策略要求端口也必须一致。通常,这不会成为一个很大的问题。但是你很有可能会同一个域名编写worker和client,所以知道这点对你总是有所帮助。
整体Worker具体步骤就是这样的 ,下面完整写一个主线程发给子线程一个数组数据,然后子线程处理数据数据并发回主线程的代码。
//开启了子线程
var arr = [12,5,8];
var oW = new Worker('d.js');
//发送
oW.postMessage(arr)
oW.onmessage = function (ev) {
alert(ev.data);//666,5,8
};
console.log(arr);//12,5,8
//主线程和子线程有它们各自的独立空间,信息主要是来回交换而不是共享。
d.js文件
self.onmessage = function(ev){
ev.data[0] = 666;
this.postMessage(ev.data);
};
当然,Workers不是简简单单修改一个数组这么简单了,那么什么时候可以用到多线程呢?
worker的实际发生场景可能是,你需要处理一个同步的第三方接口,于是主线程需要等待结果再进行下一步操作。这种情况下,你可以生成一个worker,由它代理,异步完成此任务。
Web worker在轮询情况下也非常适用,你可以在后台不断查询目标,并在有新数据时向主线程发送消息。
你也许遇到需要向服务端返回大量的数据的情况。通常,处理大量数据会消极影响程序的响应能力,然后导致不良用户体验。更优雅的办法是将处理工作分配给若干worker,由它们处理不重叠的数据。
还有应用场景会出现在通过多个web worker分析音频或视频的来源,每个worker针对专项问题。
译注:本人不是什么大牛,只是一个一直在学习的小程序员,如果文章内容当中有什么不对的地方请与我讨论,共同进步!