Web Worker能够理解为js在后台线程中运行的方法,它能够执行js代码而不阻塞用户UI界面。一个Web Worker能够将消息发送到建立它的JavaScript代码(只要运行在同源的父页面中,workers能够依次生成新的workers), 反之也能够从主线程接收消息
注意:worker运行在另外一个全局上下文中,不一样于当前的window。所以,使用window快捷方式获取当前全局的范围,在一个Worker内将返回错误(直接访问你须要访问的属性便可!如:console而不是window.console)。跨域
在WebWorker中有些方法和属性是不能被访问的,好比BOM的一些API和DOM相关的一些API,localStorage,SessionStorage等,可是大部分的window对象是能够被访问的好比:Websocket,XMLHttpRequest(一样不能跨域☹)Console Api,Array,Date,Math,String等等,就是说涉及到页面操做和页面中的对象通通不能被访问,它的应用场景是替代主线程执行须要消耗页面性能的代码。这里有一份关于WebWorker容许访问的方法及属性清单浏览器
经常使用worker为专用worker(仅在单一脚本中被使用)和共享worker(以同时被多个脚本使用);DedicatedWorkerGlobalScope和SharedWorkerGlobalScope对象分别表明它们的上下文socket
为了更好的错误处理控制及向下兼容须要作些兼容检测函数
if (window.Worker) { some codes ... }
调用Worker()构造函数建立一个Worker对象,该对象接收指定的URL脚本(脚本必须遵照同源策略不然将抛出错误)post
var myWorker = new Worker('worker.js');
主线程和worker线程都使用postMessage()方法发送各自的消息,使用onmessage事件处理函数来响应消息(消息被包含在Message事件的data属性中),这个过程当中数据并非被共享而是被复制。在主线程中使用时,onmessage和postMessage() 必须挂在worker对象上,而在worker中使用时不用这样作。缘由是,在worker内部,worker是有效的全局做用域。性能
/*主线程*/ //发送数据至worker myWorker.postMessage('can you hear me?'); //从worker线程监听接收数据 myWorker.onmessage = function(e) { console.log(e.data);//'I can hear you!' } /*worker线程*/ //从主线程监听接收数据 onmessage = function(e) { console.log(e.data);//'can you hear me?' //发送数据至worker e.data && postMessage('I can hear you!'); }
若是你须要从主线程中马上终止一个运行中的worker,能够调用worker的terminate方法:线程
myWorker.terminate();//worker 线程会被当即杀死
在worker线程中,workers 也能够调用本身的close方法进行关闭:code
close();
当worker出现运行中错误时,它的onerror事件处理函数会被调用。它会收到一个扩展了 ErrorEvent 接口的名为 error的事件。该事件不会冒泡而且能够被取消;为防止触发默认动做,worker能够调用错误事件的preventDefault()方法。对象
错误事件有如下三个核心的字段:
message
可读性良好的错误消息。
filename
发生错误的脚本文件名。
lineno
发生错误时所在脚本文件的行号。接口
若是须要worker可以生成更多的worker。即subworker,但必须托管在同源的父页面内。注意:subworker解析 URI时会相对于父worker的地址而不是自身页面的地址。这使得worker更容易记录它们之间的依赖关系。
Worker 线程可以访问一个全局函数importScripts()来引入脚本,该函数接受0个或者多个URI做为参数来引入资源;如下例子都是合法的:
importScripts();//什么都不引入 importScripts('foo.js');//只引入"foo.js importScripts('foo.js', 'bar.js');//引入两个脚本
注意: 脚本的下载顺序不固定,但执行时会按照传入 importScripts() 中的文件名顺序进行。这个过程是同步完成的;直到全部脚本都下载并运行完毕, importScripts() 才会返回。
一个共享worker能够被多个脚本使用——即便这些脚本正在被不一样的window、iframe或者worker访问。
var myWorker = new SharedWorker('worker.js');//和专用worker不一样构造器为SharedWorker
和专用worker不一样的是与一个共享worker通讯必须经过端口对象即一个确切的打开的端口供脚本与worker通讯(在专用worker中这一部分是隐式进行的)。
在传递消息以前,端口链接必须被显式的打开,打开方式是使用onmessage事件处理函数或者start()方法:
//方式1 myWorker.port.onmessage = function(e) { ... } //方式2(只在一种状况下须要,那就是消息事件被addEventListener()方法使用。) myWorker.port.start(); myWorker.port.addEventListener('message',function(e){ ... })
而后就能够像以前那样发送和接收消息了,可是postMessage()方法必须被端口对象调用:
/*主线程*/ myWorker.port.postMessage('I posted some message!');//发送 myWorker.port.onmessage = function(e) {//监听接收 ... } /*worker线程*/ onconnect = function(e) { var port = e.ports[0]; port.onmessage = function(e) { var workerResult = 'Result: ' + (e.data[0] * e.data[1]); port.postMessage(workerResult); } }
在worker线程中须要注意的是:当一个端口链接被建立时(例如:在父级线程中,设置onmessage事件处理函数,或者显式调用start()方法时),使用onconnect事件处理函数来执行代码。诸如postMessage()和onmessage也必须在端口链接上访问。
特性 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|
基础支持 | 4 | 3.5 (1.9.1) | 10.0 | 10.6 | 4 |
共享worker | 4 | 29 | 未实现 | 10.6 | 6.1 |
特性 | Android | Chrome for Android | Firefox Mobile (Gecko) | Firefox OS (Gecko) | IE Phone | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|
基础支持 | 4.4 | 4 | 3.5 | 1.0.1 | 10.0 | 11.5 | 5.1 |
共享worker | 未实现 | 4 | 8 | 1.0.1 | 未实现 | 未实现 | 未实现 |