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 };
執行結果:
不會卡住主進程界面,大批量計算在分線程中執行。