Event Loop
- Event Loop : 瀏覽器使用 Event Loop 來協調 DOM 事件、UI 渲染、腳本執行和網絡事件等。
- Task Queue (Event Queue) :每當 DOM 事件、計時器事件或者網絡事件被觸發時,它們的回調函數和 Context 都會被壓入 Event Queue,而 Event Loop 則會從中取出回調函數並執行。
雖然JavaScript是單線程的(按順序執行的主線程),但維護事件隊列的是另一個線程(Event Loop)。每當某個事件被觸發,它的回調函數就會等待在這個隊列(Event Queue)里。
異步方法最主要有2點,一個是不阻塞當前代碼的執行,另一個是有回調方法。即異步方法運行完可以通知主線程。
Event Loop有
browsing contexts和 workers兩種類型。一個
event loop可以有一個或多個task queues。來自同一個task source的所有tasks必須放入同一個task queue。
通常有4種task source:DOM manipulation task source,user interaction task source,networking task source和history traversal task source。
同一個task queue是按先進先出順序執行的。瀏覽器可以根據task queue中task source的不同,給予task queue不同的優先級。即由瀏覽器決定挑哪一個task queue中的隊首task執行。
瀏覽器是多線程的,它們在內核制控下相互配合以保持同步。一個瀏覽器至少實現三個常駐線程:JavaScript引擎線程,GUI渲染線程,瀏覽器事件觸發線程(UI線程)。
1) javascript引擎是基於事件驅動單線程執行的。JS引擎一直等待着event loop中任務的到來,然后加以處理(只有當前函數執行棧執行完畢,才會去任務隊列中取任務執行)。瀏覽器無論什么時候都只有一個JS線程在運行JS程序。
2) UI渲染線程負責渲染瀏覽器界面,當界面需要重繪(Repaint)或由於某種操作引發回流(reflow)時,該線程就會執行。但是 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被掛起,JS對頁面的操作即GUI的更新也會被保存在一個隊列中,等到JS引擎空閑時才有機會被執行。這就是JS阻塞頁面加載。
3) 事件觸發線程,當一個事件被觸發時該線程會把事件添加到任務隊列的隊尾,等待JS引擎的處理。這些事件可以來自JavaScript引擎當前執行的代碼塊調用setTimeout/ajax添加一個任務,也可以來自瀏覽器其他線程如鼠標點擊添加的任務。但由於JS的單線程關系,所有這些事件都得排隊等待JS引擎處理。
javascript要等主線程空了才會去查看子線程有沒有回調內容。異步的任務執行的順序是不固定的,主要看返回的速度。
function f() { console.log("foo"); setTimeout(g, 0); console.log("baz"); h(); } function g() { console.log("bar"); } function h() { console.log("blix"); } f(); 輸出的結果為:foo 、baz 、 blix 、bar
瀏覽器的多線程技術
Web Worker(可開啟獨立運行在瀏覽器后台的js環境)
Nodejs的異步任務執行流程
用戶寫的代碼是單線程的,但nodejs內部並不是單線程!
Node.js不是用多個線程為每個請求執行工作的,相反而是它把所有工作添加到一個事件隊列中,然后有一個單獨線程,來循環提取隊列中的事件。事件循環線程抓取事件隊列中最上面的條目,執行它,然后抓取下一個條目。當執行長期運行或有阻塞I/O的代碼時,注意這里:它不會被阻塞,會繼續提取下一個事件,而對於被阻塞的事件Node.js會從線程池中取出一個線程來運行這個被阻塞的代碼,同時把當前事件本身和它的回調事件一同添加到事件隊列(callback嵌套callback)。
當Node.js事件隊列中的所有事件都被執行完成時,Node.js應用程序終止。
Nodejs架構
點餐的廚房的例子:整個過程沒有阻塞新用戶的連接,也不需要維護連接。
基於這樣的機制,理論上陸續有用戶請求連接,NodeJS都可以進行響應,因此NodeJS能支持比Java、php程序更高的並發量。
雖然維護事件隊列也需要成本,再由於NodeJS是單線程,事件隊列越長,得到響應的時間就越長,並發量上去還是會力不從心。
RESTful API是NodeJS最理想的應用場景,可以處理數萬條連接,本身沒有太多的邏輯,只需要請求API,組織數據進行返回即可。