JS线程机制与事件机制
1.进程与线程
(1).定义:
-
进程:程序的一次执行,它占有一片独有的内存空间
-
CPU的基本调度单位,是程序执行的一个完整的流程
(2).进程与线程的关联
-
一个进程一般至少有一个运行的线程:主线程
-
一个进程可以运行多个线程
-
一个进程内的数据可以供其中的多个线程共享
-
多个线程之间的数据是不能直接共享的
(3).浏览器基本上是多进程的
2.浏览器内核
(1).定义:支持浏览器运行的最核心的程序
(2).不同的浏览器运行的内核不同
-
Chrome,Safari:webkit
-
firefox:Gecko
-
IE:Trident
-
国内浏览器360等:Trident + webkit
(3).内核组成的模块:
-
html,css文档解析模块:负责页面文本的解析
-
dom/css模块: 负责dom/css在内存中的相关处理
-
布局和渲染模块:负责页面的布局和效果的绘制
-
定时器模块:负责定时器的管理
-
网络请求模块:负责服务器请求(Ajax)
-
事件响应模块:负责事件的管理
3.定时器
(1)分类:
-
循环定时器:不关闭一直执行
-
延时定时器:一定时间后才执行,只执行一次
(2)循环定时器:setInterval
1 var i = 0; 2 //获得定时器句柄 3 var intervalId = setInterval(function(){ 4 if (i >= 5) { 5 //清除定时器 6 clearInterval(intervalId); 7 } 8 console.log(Date.now()); 9 i++; 10 },1000);
(3)延时定时器:
1 setTimeout(function(){ 2 console.log("----"); 3 },2000);
4.JS是单进程的
(1)证明:
-
使用setTimeout()回调函数在主线程运行
-
定时器回调函数只有在运行栈中的代码全部执行完毕后才可能执行
(2)为什么js要使用单线程模式:
作为浏览器的脚本语言主要目的是和用户交互,以及操作DOM,单线程会避免复杂的同步问题
(3)代码分类:
-
初始化代码
-
回调代码
(4)JS引擎执行代码的基本流程
-
先执行初始化代码:包括一些特别的代码:
-
设定定时器
-
绑定监听
-
发送Ajax请求
-
-
在某一时刻执行回调代码
5.事件循环模型
执行流程:
1.同步任务加载执行
初始化代码:绑定监听,设置定时器,发送ajax请求
2.异步任务交给时间管理模块
3.管理模块监听异步任务是否满足条件,如果满足条件就会将对应的任务放入callback queue中
4.主线程同步任务执行完成后通过event loop(事件轮询机制)询问callback queue
-
有可执行的回调函数,就将回调函数放入主线程中执行
-
如果没有待会再来询问
6.Web Workers:(需要开启服务器)
(1)提供了js分线程实现
(2)相关API:
-
Worker:构造函数,加载分线程执行的js文件
-
Worker.prototype.onmessage:用于接收另一个线程的回调函数
-
Worker.prototype.postMessage:向另一个线程发送信息
(3)不足:
-
不能操作DOM(不能更新UI)
-
不能跨域加载JS
-
不是每一个浏览器都支持这个新特性
(4)代码:
在主线程html中编写
1 <input type="text" id="number" value="30"> 2 <button id="btn">计算斐波那契数</button> 3 <script type="text/javascript"> 4 5 6 7 document.getElementById("btn").onclick = function(){ 8 var value = document.getElementById("number").value; 9 10 //获得分线程 11 var worker = new Worker("./work.js"); 12 13 //发送给分线程数据 14 worker.postMessage(value); 15 //接收分线程数据 16 worker.onmessage = function(event){ 17 console.log(event.data); 18 } 19 20 } 21 </script>
在同一级目录下work.js
1 function fibonacci(num){ 2 return num > 2 ? fibonacci(num - 1) + fibonacci(num - 2) : 1; 3 } 4 5 var onmessage = function(event){ 6 console.log("分线程监视...."); 7 8 //获取主线程发送过来的数据 9 var data = event.data; 10 11 //分线程处理数据 12 data = fibonacci(data); 13 14 //返回数据给主线程 15 postMessage(data); 16 };
执行结果:
不会卡住主进程界面,大批量计算在分线程中执行。