一、JS代码是单线程的?
- 定时器执行时候是在主线程中执行的
- 定时器回调函数只能在主线程中代码执行完毕后在进行执行
二、为什么JS是单线程的不是多线程?
这与他的用途有关,JS作为浏览器脚本语言,主要用途是与用户互动,以及操作DOM。 这决定了它只能是单线程,否则会带来很复杂的同步问题
三、H5中关于JS分线程,叫做Web Workers
事件循回模型
- 所有代码分类
- 初始化执行代码(同步代码): 包含绑定dom事件监听, 设置定时器, 发送ajax请求的代码
- 回调执行代码(异步代码): 处理回调逻辑
- js引擎执行代码的基本流程:
- 初始化代码===>回调代码
- 模型的2个重要组成部分:
- 事件管理模块
- 回调队列
- 模型的运转流程
- 执行初始化代码, 将事件回调函数交给对应模块管理
- 当事件发生时, 管理模块会将回调函数及其数据添加到回调列队中
- 只有当初始化代码执行完后(可能要一定时间), 才会遍历读取回调队列中的回调函数执行
图示
四、相关API
- Worker:构造函数,加载分线程执行的JS文件
- Worker.prototype.onmessage
- Worker.prototype.postMessage
五、一般步骤
1、主线程
// 主线程
var worker = new Worker('./worker.js');
// 绑定事件监听
worker.onmessage=function (event) {
console.log('分线程传回来的数据'+event)
console.log(event.data)
}
// 向分线程绑定发送待处理的数据
worker.postMessage('成功')
2、分线程
//绑定监听,监听主线程返回来的数据
var onmessage = function (event) {
console.log('主线程发送过来的数据'+event);
// 处理event中的数据
// 返回给主线程
postMessage(result);
}
六、Web Workers实际应用
需求:计算得到fibonacci数列中第n个数的值
在主线程计算: 当位数较大时, 会阻塞主线程, 导致界面卡死
在分线程计算: 不会阻塞主线程
源码实现:
主线程:
<script type="text/javascript">
document.getElementById('btn2').onclick=function () {
// 主线程
var worker = new Worker('./worker.js');
// 绑定事件监听
worker.onmessage=function (event) {
console.log('分线程传回来的数据'+event)
console.log(event.data)
}
// 向分线程绑定发送待处理的数据
var value = document.getElementById('number').value;
worker.postMessage(value)
}
</script>
worker.js,分线程:
//绑定监听,监听主线程返回来的数据
var onmessage = function (event) {
console.log('主线程发送过来的数据'+event);
function fi(n) {
return n>2 ? fi(n-1)+fi(n-2):1;
}
// 处理event中的数据
var result = fi(event.data);
// 返回给主线程
postMessage(result);
}
七、不足
- worker内代码不能操作DOM(更新UI)
- 不能跨域加载JS
- 不是每个浏览器都支持这个新特性