Web Workers 是 HTML5 提供的一个javascript多线程解决方案,我们可以将一些大计算量的代码交由web Worker运行而不冻结用户界面。在浏览器后台运行JavaScript, 而不占用浏览器自身线程。Web Worker可以提高应用的总体性能,并且提升用户体验。
学习自:
原文1
原文2
//test.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<script type="text/javascript">
//WEB页主线程
var worker =new Worker("worker.js"); //创建一个Worker对象并向它传递将在新线程中执行的脚本的URL
worker.postMessage("hello world"); //向worker发送数据
worker.onmessage =function(evt){ //接收worker传过来的数据函数
console.log(evt.data); //输出worker发送来的数据
}
</script>
</body>
</html>
//worker.js
onmessage =function (evt){
var d = evt.data;//通过evt.data获得发送来的数据
console.log(evt)
postMessage( d );//将获取到的数据发送会主线程
}
//在chrome中不可以运行
如果不用web worker:
document.querySelector('div').onclick = function() {
console.log('hello world');
};
function fibonacci(n) {
return n < 2 ? n : arguments.callee(n - 1) + arguments.callee(n - 2);
}
console.log(fibonacci(36));
//只有在等计算完成后才打印hello world
关于web worker的七件事
Web Worker 可以让你在后台运行Javascript
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>web worker fibonacci</title>
</head>
<body>
<script type="text/javascript">
onload =function(){
var worker =new Worker('fibonacci.js');
worker.addEventListener('message', function(event) {
var timer2 = (new Date()).valueOf();
console.log( '结果:'+event.data, '时间:'+ timer2, '用时:'+ ( timer2 - timer ) );
}, false);
var timer = (new Date()).valueOf();
console.log('开始计算:40','时间:'+ timer );
setTimeout(function(){
console.log('定时器函数在计算数列时执行了', '时间:'+ (new Date()).valueOf() );
},1000);
worker.postMessage(40);
console.log('我在计算数列的时候执行了', '时间:'+ (new Date()).valueOf() );
}
</script>
</body>
</html>
//fibonacci.js
var fibonacci =function(n) {
return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);
};
onmessage =function(event) {
var n = parseInt(event.data, 10);
postMessage(fibonacci(n));
};
//控制台:
开始计算:40 时间:1492829709415
我在计算数列的时候执行了 时间:1492829709419
定时器函数在计算数列时执行了 时间:1492829710419
结果:102334155 时间:1492829780583 用时:71168
限制:
- Web Worker无法访问DOM节点;
- Web Worker无法访问全局变量或是全局函数;
- Web Worker无法调用alert()或者confirm之类的函数;
- Web Worker无法访问window、document之类的浏览器全局变量;
不过Web Worker中的Javascript依然可以使用setTimeout(),setInterval()之类的函数,也可以使用XMLHttpRequest对象来做Ajax通信。
两种web worker
- 专用线程dedicated web worker
只能被创建它的页面访问, 随当前页面的关闭而结束
//time.js
addEventListener('message',function(evt) {
setTimeout(function(){
console.log('finish')
postMessage(200)
},evt.data)
})
//time.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<button>click me</button>
<script>
var el = document.querySelector('button');
el.addEventListener('click',function() {
var worker = new Worker('time.js');
worker.addEventListener('message',function(evt) {
console.log('success')
},false)
setTimeout(function(){
console.log('in')
},1000)
worker.postMessage(5000)
console.log('begin')
},false)
</script>
</body>
</html>
//控制台
begin
in
finish
success
- 共享线程shared web worker
为多个页面服务。在这种情况下,我们会创建一个共享线程的Shared web worker,它可以被与之相关联的多个页面访问,只有当所有关联的的页面都关闭的时候,该Shared web worker才会结束。
// shared_worker.js
function factorial(num){
var i = 1,
result = 1;
for (; i <= num; i ++){
result *= i;
}
return result;
}
var count = 0;
self.addEventListener('connect', function(event){
var port = event.ports[0]
port.onmessage = function(event){
var number = 0;
count += 1;
if (event.data){
number = parseInt(event.data, 10) || 0;
if (number > 0){
number = factorial(number);
}
}
port.postMessage("count " + count + ": " + number);
};
port.start();
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>using web worker</title>
</head>
<body>
<script>
function showMsg(msg){
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
var worker = new SharedWorker('../js/shared_worker.js');
worker.port.postMessage('60');
worker.port.onmessage = function(event){
showMsg(event.data);
};
worker.port.onerror = function(event){
showMsg(event.message);
}
var worker1 = new SharedWorker('../js/shared_worker.js');
worker1.port.postMessage('10');
worker1.port.onmessage = function(event){
showMsg("worker1: " + event.data);
};
worker1.port.onerror = function(event){
showMsg("worker1 " + event.message);
}
worker1.onerror = function(event){
showMsg("worker1 " + event.message);
}
showMsg("shared worker start.");
</script>
</body>
</html>
Web Worker使用XMLHttpRequest与服务端通信
通过Error事件捕捉错误信息
通过terminate()方法终止Web Worker
优点
- 可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信
- 可以使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()
- 可以使用XMLHttpRequest来发送请求
- 可以访问navigator的部分属性