前提
在使用Worker之前,首先要检测浏览器是否支持这个API
[注意]IE9-浏览器不支持
if (window.Worker) { // to do }
使用Web Worker有以下几点限制:
同域限制。子线程加载的脚本文件,必须与主线程的脚本文件在同一个域
DOM限制。子线程所在的全局对象,与主进程不一样,它无法读取网页的DOM对象,即document、window、parent这些对象,子线程都无法得到。(但是,navigator对象和location对象可以获得。)
脚本限制。子线程无法读取网页的全局变量和函数,也不能执行alert和confirm方法,不过可以执行setInterval和setTimeout,以及使用XMLHttpRequest对象发出AJAX请求
文件限制。子线程无法读取本地文件,即子线程无法打开本机的文件系统(file://),它所加载的脚本,必须来自网络
主线程
【新建】
主线程采用new命令,调用Worker构造函数,可以新建一个子线程
var worker = new Worker('work.js');
Worker构造函数的参数是一个脚本文件,这个文件就是子线程所要完成的任务,上面代码中是work.js
这行代码会导致浏览器下载work.js,但只有Worker接收到消息才会实际执行文件中的代码
由于子线程不能读取本地文件系统,所以这个脚本文件必须来自网络端。如果下载没有成功,比如出现404错误,这个子线程就会默默地失败
【传递消息】
要给Worker传递消息,可以使用postMessage()方法。postMessage()方法的参数,就是主线程传给子线程的信号。它可以是一个字符串,也可以是一个对象
一般来说,可以序列化为JSON结构的任何值都可以作为参数传递给postMessage()。换句话说,这就意味着传入的值是被复制到Worker中,而非直接传过去的
worker.postMessage("Hello World"); worker.postMessage({method: 'echo', args: ['Work']});
只要符合父线程的同源政策,Worker线程自己也能新建Worker线程。Worker线程可以使用XMLHttpRequest进行网络I/O,但是XMLHttpRequest对象的responseXML和channel属性总是返回null
【事件监听】
主线程使用onmessage事件来监听子线程发来的信息。来自子线程Worker的数据保存在event.data中。Worker返回的数据也可以是任何能够被序列化的值
worker.addEventListener('message', function(e) { //对数据进行处理 console.log(e.data); }, false);
【错误处理】
如果子线程发生错误,会触发主线程的error事件。error事件的事件对象中包含三个属性:filename、lineno和message,分别表示发生错误的文件名、代码行号和完整的错误消息
worker.onerror = function(event){ console.log("ERROR:"+event.filename+"("+event.lineno+"):"+event.message); };
建议在使用Web Worker时,始终都要使用onerror事件处理程序,即使这个函数除了把错误记录到日志中什么也不做都可以。否则,Worker就会在发生错误时,悄无声息地失败了
【停止子线程】
任何时候,只要调用terminate()方法就可以停止Worker的工作。而且,Worker中的代码会立即停止执行,后续的所有过程都不会再发生(包括error和message事件也不会再触发)
worker.terminate();//立即停止 Worker 的工作
子线程
【作用域】
关于子线程Web Worker,最重要的是要知道它所执行的javascript代码完全在另一个作用域中,与当前网页中的代码不共享作用域。在Web Worker中,同样有一个全局对象和其他对象以及方法
Web Worker中的全局对象是worker对象本身。也就是说,在这个特殊的全局作用域中,this和self引用的都是worker对象。为便于处理数据,Web Worker本身也是一个最小化的运行环境,包括以下:
1、最小化的navigator对象,包括onLine、appName、appVersion、userAgent和platform属性
2、只读的location对象
3、setTimeout()、setInterval()、clearTimeout()和clearInterval()方法
4、XMLHttpReguest构造函数
显然,Web Worker的运行环境与页面环境相比,功能是相当有限的
【事件监听】
当主线程在worker对象上调用postMessage()时,数据会以异步方式被传递给子线程worker,进而触发子线程worker中的message事件。为了处理来自页面的数据,同样也需要创建一个onmessage事件处理程序
self代表子线程自身,self.addEventListener表示对子线程的message事件指定回调函数(直接指定onmessage属性的值也可)。回调函数的参数是一个事件对象,它的data属性包含主线程发来的信号
/* File: work.js */self.addEventListener('message', function(e){var data = event.data;//处理数据}, false);
【传递消息】
子线程使用postMessage()方法向主线程传递信息
/* File: work.js */self.onmessage = function(e) {var data = e.data;//处理数据var method = data.method;var args = data.args;var reply = doSomething(args); self.postMessage({method: method, reply: reply}); };
【包含脚本】
无法在子线程Worker中动态创建新的