事件循環學習筆記

JavaScript是單線程
JavaScript的單線程,與他的用途有關。做爲瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操做DOM 。這決定了它只能是單線程,不然會帶來很複雜的同步問題。好比:假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另外一個線程刪除了這個節點,這是瀏覽器不知道應該以哪一個線程爲準。瀏覽器

因此,爲了不復雜性,從一誕生,JavaScript就是單線程,這已經成爲這門語言的核心特徵,未來也不會改變。網絡

爲了利用多核CPU的計算能力,HTML5提出Web Worker標準,容許JavaScript腳本建立多個線程,可是子線程徹底受線程控制,且不得操做DOM。因此,這個新標準並無改變JavaScript單線程的本質。數據結構

任務隊列
單線程就意味着,全部任務須要排隊,前一個任務結束,纔會執行後一個任務。若是前一個任務耗時很長,後一個任務就必須一直等着。異步

若是排隊是由於計算量大,CUP忙不過來,倒也算了,可是不少時候CUP是閒着的,由於IO設爲很慢,不得不等着結果出來,再往下執行。(IO設備指的是輸入輸出設備)(好比Ajax操做從網絡讀取數據很慢,頁面等待數據讀取成功後纔會繼續去執行後面代碼。若是由於某些緣由,數據很慢,這時後面的代碼就不會被執行。)async

JavaScript語言的設計者意識到,這時主線程徹底能夠無論IO設備,將等待中的任務掛起,先運行排在後面的任務。等到IO設備返回告終果,再回頭把掛起的任務繼續執行下去。函數

因而,全部任務能夠分紅兩種,一種是同步任務,另外一種是異步任務。
同步任務(synchronous)
指的是,在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務;
異步任務(asynchronous)
指的是,不進入主線程、而是進入「任務隊列」的任務,只有「任務隊列」通知主線程,某個異步任務能夠執行了, 該任務纔會進入主線程執行。(任務隊列爲task queue)oop

具體來講,異步執行的運行機制以下。線程

1.全部同步任務都在主線程上執行,造成一個執行棧。(execution context stack)。
2.主線程以外,還存在一個「任務隊列」(task queue)。只要異步任務有了運行結果,就在「任務隊列」之中放置一個事件。
3.一旦「執行棧」中的全部同步任務執行完畢,系統就會讀取「任務隊列」,看看裏面有哪些事件。那些對應的異步任務,結束等待狀態,進入執行棧,開始執行。
4.主線程不斷重複上面的第三步。設計

只要主線程空了,就會去讀取「任務隊列」,這就是JavaScript的運行機制。這個過程會不斷重複。隊列

事件和回調函數
「任務隊列」是一個事件的隊列,IO設備完成一項任務,就在「任務隊列」中添加一個事件,表示相關的異步任務能夠進入「執行棧」了。主線程讀取「任務隊列」,就是讀取裏面有哪些事件。

「任務隊列」中的事件,除了IO設備的事件之外,還包括一些用戶產生的事件(好比鼠標點擊,頁面滾動等等)。只要指定過回調函數,這些事件發生時就會進入「任務隊列」,等待主線程讀取。

所謂「回調函數」(callback),就是那些會被主線程掛起來的代碼。異步任務必須指定回調函數,當主線程開始執行異步任務,就是執行對應的回調函數。

「任務隊列」是一個先進先出的數據結構,排在前面的事件,優先被主線程讀取。主線程的讀取過程基本上是自動的,只要執行棧一清空,「任務隊列」上第一位的事件就自動進入主線程。可是,猶豫存在後文提到的「定時器」功能,主線程首先要檢查一下執行時間,某些事件只有到了規定的時間,才能返回主線程。

Event Loop主線程從「任務隊列」中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制又稱爲EventLoop(事件循環)。

相關文章
相關標籤/搜索