众所周知javascript是单线程的,特点就是容易出现阻塞。如果一段程序处理时间很长,很容易导致整个页面hold住。什么交互都处理不了怎么办?
复杂逻辑后端处理
html5的Web Workers
setTimeout
1.setTimeout
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1> this is a header</h1>
</body>
<script>
window.onload=function(){
var processTime = 0;
//1.常规操作
// tcCircle();
function tcCircle(){
var arr = new Array(10);
for(var i=0;i<arr.length;i++){
process(arr[i]);
}
//页面标题栏一直转圈 且下面的语句迟迟无法执行,页面也无法加载
console.log("long process finish!");
}
//2.执行setTimeout数组分块操作,利用setTimeout延时调用
var arr = new Array(10);
var i=0;
var timer;
timer=setTimeout(tcCircleUseSetTimeout,0);
function tcCircleUseSetTimeout(){
process(arr[i++]);
if(i<10){
//如果没处理完,下一次Event Loop继续处理
// timer=setTimeout(tcCircleUseSetTimeout,0);
timer=setTimeout(arguments.callee,0);
}else{
console.log("long process finish!");
}
}
function process(ele){
console.log("process"+(++processTime));
//模拟长时间的处理过程
sleep(1000);
}
//利用死循环模拟处理某个时间的过程
function sleep(sleepTime){
var start=new Date().getTime();
while(true){
if(new Date().getTime()-start>sleepTime){
break;
}
}
}
}
</script>
</html>
2.工作线程Web Workers
Web Worker的基本原理就是在当前javascript的主线程中,使用Worker类加载一个javascript文件来开辟一个新的线程,起到互不阻塞执行的效果,并且提供主线程和新线程之间数据交换的接口:postMessage,onmessage。
index.html
<body>
<h1> this is a header</h1>
</body>
<script>
window.onload=function(){
if (window.Worker) {
var worker =new Worker('javascripts/fibonacci.js');
worker.addEventListener('message', function(event) {
var timer2 =new Date().valueOf();
console.log( '结果:'+event.data, '时间:'+ timer2, '用时:'+ ( timer2 - timer1 ) );
}, false);
worker.postMessage(40);
var timer1 = (new Date()).valueOf();
console.log('开始计算fibonacci(40)','时间:'+ timer1 );
console.log('这是在计算fibonacci(40)的时候执行', '时间:'+ new Date().valueOf());
}
}
</script>
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));
};
结果:
WebWorker 可以做什么:
(1)可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信
(2)可以在worker中通过importScripts(url)加载另外的脚本文件
(3)可以使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()
(4)可以使用XMLHttpRequest来发送请求
说明:Ajax 和 Web Worker 都是异步执行的,似乎没有必要在Web Worker里调用Ajax,如果存在这种情况,Ajax 需要按照一个队列里数据排列的顺序同步发送请求,如果不想页面被阻塞,这种情况下可以使用Web Worker 并且需要在Web Worker里使用Ajax。
局限性:
(1)Web Worker 不支持跨域
(2)worker内不能访问DOM
(3)各个浏览器对Worker的实现不大一致,例如FF里允许worker中创建新的worker,而Chrome中就不行
(4)无法访问 LocalStorage,和对 dom 元素的限制一样,因为读写 LocalStorage 是同步的,一定会引起 race condition
其他
HTML5 之 Web Worker
深入 HTML5 Web Worker 应用实践:多线程编程
WebWorker实战使用
聊聊 webworker