之前一直会有疑问,js是单线程的,那如何实现的前端向后台发送多个http请求,还同时维护这么多请求的会话,今天就来深入探寻下浏览器线程和js线程
首先,js的单线程是指浏览器的js引擎是单线程的,不过浏览器还包含了其他的线程:
- js引擎线程
- 页面渲染线程
- http请求线程
- 事件触发线程
- EventLoop轮询的处理线程
这几个线程的主要作用:
页面渲染线程:就是负责渲染页面的,因为js会影响页面的渲染,所以页面渲染线程和js引擎是互斥的
js引擎线程:js引擎线程也不是单线程的,而是包含主线程和其他线程,主线程是主要处理js任务的,是从消息队列里去拿任务进行单线程处理,那就需要一个线程负责把js任务放入到消息队列中,这就需要Eventloop的轮询,查看页面交互,点击事件,异步的http线程返回的结果,之后要处理,就会放到消息队列中
setTimeout(function () { while (true) { } }, 1000);
setTimeout(function () { console.log('end 2'); }, 2000);
setTimeout(function () { console.log('end 1'); }, 100);
console.log('end');
这段代码中,会输出 end,end1,然后浏览器假死,为什么按照时间,console.log(‘end 2’);这个方法是在消息队列中排在while (true) { } 执行的后面,不过while (true) { }这个同步任务js的引擎线程会一直执行,所以永远执行不到console.log(‘end 2’),除非中间跳出任务,才会执行到下个任务
html5也推出了多线程功能,Worker类
//主线程
worker.addEventListener('message', function(e){
//e.data为从worker线程得到的数据
});
worker.possMessage(...);//向worker线程发送数据
//工作线程
addEventListener('message', function(e){
//e.data为从主线程得到的数据
});
possMessage(...);//向主线程发送数据
例如:
//worker.js
function calculate(){
var ret = 0;
for(var i = 1; i <= 1e9; i++){
ret += i;
}
return ret;
}
postMessage(calculate());
//demo.js
var worker = new Worker('scripts/worker.js');
worker.addEventListener('message', function(e){
console.log(e.data); //500000000067109000
}, false);