js是单线程的:javascript作为脚本语言,主要与用户交互,以及Dom操作,这就决定了js只能是单线程,否则会带来很复杂的同步问题。
- h5提供js分线程 web workers:可以将一些计算量大的代码交由web worker运行而不冻结用户界面。
- Worker API
worker构造函数,加载分栈执行的js文件
worker.prototype.onmessage:用于接收另外一个线程的回调函数
worker.prototype.postMessage向另外一个函数发送消息
3.缺点 :
但是worker代码不能直接操作dom,不能跨域加载js,不是每个浏览器都支持这个新特性,可以不阻塞主线程
使用:创建在分线程执行js文件,在主线程js中发送消息并设置回调
例子:在html页面中,让分线程计算斐波拉数列,然后返回数据
<body>
<input type="text" placeholder="数值" id="num">
<button id="btn">计算</button>
</body>
<script>
var input = document.getElementById('num');
var btn = document.getElementById('btn');
btn.onclick = function(){
var number = input.value;
// 创建一个worker对象
var worker = new Worker("worker.js");
// 向分线程发送消息
worker.postMessage(number);
console.log('主线程向分线程发送数据')
// 绑定接收消息
worker.onmessage = function(event){
console.log("主线程接收分线程返回的数据");
alert(event.data);
// event.data 就是返回的数据
}
}
</script>
worker通过new方式创建出来,并且写入分线程的途径,这里采用相对路径,同于目录下的worker文件
worker.js文件
var onmessage = function(event){
// event.data就是接受的数据
// 不能函数声明
var number = event.data;
console.log('分线程接收到主线程的数据'+number);
// 计算
var result = fibonacci(number);
postMessage(result);
console.log("分线程向主线程传递数据");
console.log(this);
// 全局对象就不是window了
// 并且此页面根本就不可访问window对象
// 分线程中的全局对象不再是window,所以在分线程中不可能再更新界面
function fibonacci(n){
return n<=2 ? 1:fibonacci(n-1)+fibonacci(n-2);
// 递归调用函数内部调用自己
}
}
worker文件返回数据的时候也采用postMessage的方法,但是在这个this并不是在html中window对象,所以操作不了界面。
这样因为计算结果可能比较久,因为js单线程,所以此时前端页面交互阻塞,如果交给worker去处理,虽然数据返回结果较慢,但是用户可以继续操作界面。