概念
解决JS单线程,遇到计算密集型或高延迟的任务时发生阻塞的问题
Web Worker 的作用,就是允许主线程创建 Worker 线程,承担一些费时的任务
Worker线程可以有多个,但是使用完最好计时关闭
一个简单的例子帮助理解
改进前:
1 2 3 4 5 6 7 8 9 10 11 12
| <body> <button id="btn">点击</button> <h1 id="num"></h1> <script> for (var i = 0; i < 1000000000; i++) { } num.innerHTML = i; box.onclick = function () { alert("耗时操作导致页面阻塞,打开慢"); } </script> </body>
|
主线程中存在耗时任务,发生阻塞
改进后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <body> <button id="btn">点击</button> <button id="stop">停止子线程</button> <h1 id="num"></h1> <script> var webWorker = new Worker('./worker.js') webWorker.onmessage = function (e) { num.innerHTML = e.data } btn.onclick = function () { alert("有子线程后主线程快得多了"); } stop.onclick = function () { webworker.terminate(); } </script> </body>
|
子线程:
1 2 3 4 5 6
| (function () { for (var i = 0; i < 1000000000; i++) { } postMessage(i); })();
|
在主线程创建web worker子线程,让子线程承担费时任务,主线程不会阻塞
Web Worker的限制
- new 传递的脚本文件必须来源网络并同源
- 无法访问DOM节点;
- 无法调用alert()或者confirm之类的函数;
- 无法访问window、document之类的浏览器全局变量;但是可以用navigator对象和location对象
不过Web Worker中的Javascript依然可以使用setTimeout(),setInterval()之类的函数,也可以使用XMLHttpRequest对象来做Ajax通信
使用方法
主线程
1 2 3 4
| var worker = new Worker('work.js') worker.postMessage('Hello World'); worker.onmessage = function(ev) { console.log(ev.data) } worker.terminate()
|
worker线程
1 2 3
| addEventListener('message', function (evt) { console.log(ev.data) } self.postMessage('Hello World') self.close()
|
使用XMLHttpRequest与服务端通信
在子线程文件中写:
1 2 3 4 5 6 7 8
| addEventListener("message", function(evt){ var xhr = new XMLHttpRequest(); xhr.open("GET", "某个服务器的url"); xhr.onload = function(){ postMessage(xhr.responseText); }; xhr.send(); },false);
|
上面的代码向服务器发出GET请求,并注册了获取数据后的onload事件。结果是获得数据后把数据传给主线程
通过Error事件捕捉错误信息
Web Worker恰恰提供了error事件,供开发者捕捉错误信息
1 2 3 4 5 6
| var worker = new Worker("scripts/lengthytask.js"); worker.addEventListener("error", function(evt){ alert("Line #" + evt.lineno + " - " + evt.message + " in " + evt.filename); }, false); worker.postMessage(10000); });
|
如上可见, Worker对象可以绑定error事件;而且evt对象中包含错误所在的代码文件(evt.filename)、错误所在的代码行数(evt.lineno)、以及错误信息
参考资料
阮一峰-Web Worker 使用教程
关于Web Worker你必须知道的7件事