深入理解事件循环机制
生活随笔
收集整理的這篇文章主要介紹了
深入理解事件循环机制
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
瀏覽器常駐的線程
- js引擎線程(解釋執行js代碼、用戶輸入、網絡請求)
- GUI線程(繪制用戶界面、與js主線程是互斥的)
- http網絡請求線程(處理用戶的get,post等請求,等返回結果后將回調函數推入任務隊列)
- 定時器觸發線程(setTimeout,setIntervat等待事件結束后把執行函數推入任務隊列中)
- 瀏覽器事件處理線程(將click,mouse等交互事件發生后將這些事件放入事件隊列中)
UI主線程負責協調運轉
【例】當js引擎是單線程的,若當前執行的函數快沒有處理完,不會執行下一個函數塊,此處寫一個死循環去證明該點
<body><button id="btn">run</button> </body> <script type="text/javascript"> var oBtn = document.getElementById('btn'); function dieLoop() {while (true) {} } oBtn.onclick = function () {console.log("a"); } </script>【結果】點擊按鈕打印"a",執行函數dieLoop(作死的人才去執行這個函數,反正我卡死了),再點擊按鈕,不執行該點擊事件
JS引擎線程和GUI線程—互斥
JS可以操作DOM元素,進而會影響到GUI的渲染結果因此JS引擎線程與GU渲染線程是互斥的。也就是說當JS引擎線程處于運行狀態時,GUI渲染線程將處于凍結狀態。
JS執行機制
- 單線程—同一時間只能做一件事
- 使用單線程的原因:js設計出來就是為了與用戶交互,處理DOM,假如js是多線程,同一時間一個線程想要修改DOM,另一個線程想要刪除DOM,問題就變得復雜許多,問題就變得復雜,如果引入“鎖”的機制,就回到了被其他語言尷尬的困境(什么被其他語言尷尬的困境?)
- 操作大量數據的解決辦法:單線程計算能力有限,大量數據需要計算渲染的話,需要配合后端進行操作(VUE和node.js配合,即SSR技術)
- 異步執行:JAvaScript是基于單線程運行的,同時又可以異步執行,一般來說這種既是單線程又是異步的語言都是基于事件來驅動的,恰好瀏覽器給JavaScript提供了這樣的環境
- 流程圖如下
解釋:
- 同步和異步任務分別進入不同的執行“場所”,同步的進入主線程,異步的進入Event Table并注冊函數
- 當指定的事情完成時,Event Table會將這個函數移入Event Queue
- 主線程內的任務執行完畢為空,會去Event Queue讀取對應的函數,進入主線程執行,
- 上述過程不斷重復,即Event Loop(事件循環)
同步任務
【例】
function foo(ot) {function bar(it) {debugger;console.log(it);}bar(10);console.log(ot); } foo(20);【結果】
【分析】
異步任務
【例】
$.ajax({url : '',data : {},success : function (data) {console.log(data);} }); console.log('run');【分析】
深入理解定時器
setTimeout的等待事件結束后并不是直接執行的,而是先推入瀏覽器的一個任務隊列,在同步隊列結束后,再依次調用任務隊列中的任務
setTimeout(function(){},0)實際上,就算JS主線程中的執行棧為空,也達不到0毫秒,根據HTML標準,最低4毫秒
setInterval是每隔一段時間把任務放到Event Queue之中
【例】
var firstTime = + new Date(); function loop(d) {for (var i = 0; i < d; i++) {console.log(i);} } loop(10000); setTimeout(function () {var time = + new Date() - firstTime;console.log(time); },100);【結果】
【分析】setTimeout并不是100毫秒之后執行的,而是100毫秒后放入任務隊列,在同步隊列的任務執行完畢后,執行任務隊列的setTimeout。
總結
以上是生活随笔為你收集整理的深入理解事件循环机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 响应式原理
- 下一篇: bootstrap内容部分API解读(1