【抄作業】javascript的單線程與異步編程

javascript是單線程的

javascript可以操作DOM,所以javascript是單線程的
爲啥?
試想下,如果javascript是多線程的,就比如現在有兩個線程,其中一個是給DOM節點添加內容,另一個是刪除這個DOM節點,這時瀏覽器應該聽誰的。爲了避免這類複雜的同步問題,javascript就被設計成單線程的了。
Web Worker怎麼說?
雖然允許使用Web Worker創建子線程,但子線程完全受控於主線程,且子線程不能操作DOM,所以Web Worker並沒有改變javascript是單線程的這一本質。

瀏覽器內核是多線程的

javascript是單線程的就意味着, 只有等待上一個任務執行完,下一個任務纔會開始執行。
就像醫院排隊候診一樣,如果因爲病情複雜需要醫生花費更多的時間去分析診斷比如,任務計算量大,不得不讓大家多等會兒,可以理解。但是,輪到一位女士時,她卻說“哎呀呀,我得回家取趟病例先,再等我two hours”。讓大家空等?當然不會,醫生會讓這位“麻煩女士”先回家取病例,等她取回病例了,她必須在“等候區”等待,直到醫生將之前排隊的病人全部診斷完畢,空閒下來了,才輪到這位“麻煩女士”。
在這裏插入圖片描述
這個"等候區"就是任務隊列任務隊列裏有什麼?那我們就得了解下瀏覽器內核裏有啥線程。

瀏覽器內核裏的線程
定時器線程

setTimeoutsetInterval不是由js引擎計時,由瀏覽器內核的Timer模塊處理。
setTimeoutsetInterval所在的線程就是定時器線程。
當計時完成,回調函數就會進入任務隊列

事件觸發線程

onclickonmouseover等這些事件也不是js引擎的,由瀏覽器內核的DOM binding模塊處理。
當事件觸發時,事件處理程序會進入任務隊列

異步http請求線程

Ajax也不是js引擎的,由瀏覽器內核的Network模塊處理。網絡請求返回後,對應的回調函數也會進入任務隊列

javascript引擎線程

javascript引擎線程就是javascript線程主線程,用來執行javascript代碼。
主線程空閒後,纔會執行任務隊列中的任務。

GUI線程

負責渲染頁面,包括解析HTML、CSS,構建DOM樹、Render樹,佈局、繪製。
頁面重繪或迴流,就會運行這個線程。
你肯定聽說過,"script標籤的加載和解析會阻塞DOM渲染"或者遇到過類似下面的問題。
在這裏插入圖片描述
script標籤的加載和解析”,就是執行js代碼,即運行javascript引擎線程
“DOM渲染”,就是運行GUI線程
是的,GUI線程javascript引擎線程彼此互斥的,有你沒我,有我沒你。
javascript引擎線程運行時,GUI線程是凍結的,只有javascript引擎線程空閒時,GUI線程纔會運行。

事件循環
  • 同步任務

所有的同步任務都在主線程javascript引擎線程上執行,只有上一個任務執行完畢,下一個任務纔會開始執行。

  • 異步任務

異步任務經對應的異步線程處理後進入任務隊列。比如,setTimeout定時器線程處理後,其回調函數將被放入任務隊列
在這裏插入圖片描述
所有同步任務都在主線程上執行,因此形成一個執行棧

  1. 主線程在運行的過程中,遇異步任務會將其交給對應的異步線程。經異步線程處理後異步任務會被放入任務隊列
  2. 主線程執行完所有同步任務,空閒時,會從任務隊列中讀取異步任務,此時,異步任務將結束等待狀態進入執行棧,開始在主線程上執行。
    在這裏插入圖片描述
    1、2重複,就是事件循環

舉個簡單的例子吧。

        setTimeout(bless,0);
        function sayHi(){
            console.log("hello world");
        }
        function bless(){
            console.log("have a nice day");
        }
        sayHi();
        console.log("nice to meet you");
        console.log("nice to meet you too");
        console.log("how are you");
        console.log("I'm fine");
        console.log("thank you");
        console.log("and you");    

這裏,bless就是一個異步任務sayHi和後面一羣console.log就是同步任務,所以"have a nice day"會在最後輸出。
在這裏插入圖片描述

javascript異步編程
回調函數
事件監聽
發佈訂閱
Promise對象
Generator函數
參考文章

JS 事件循環機制
淺談瀏覽器多進程與JS線程
與JavaScript異步實現密切相關的瀏覽器內核線程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章