javascript 運行機制 EventLoop

1. 前言


  • javascript 為什么是單線程?多線程不好嗎,能提高效率啊.。

答案是不能。假設javascript有兩個線程,一個在某個DOM節點添加內容,另一個線程在這個節點上刪除內容,這是瀏覽器應該以哪個線程為準?
這就意味著單線程作為javascript的核心標準,將一直沿用下去。

  • 當然,現如今人們也意識到,單線程在保證了執行順序的同時也限制了javascript的效率,因此開發出了web worker技術。這項技術號稱讓javascript成為一門多線程語言。

使用web worker技術開的多線程有著諸多限制.
例如:所有新線程都受主線程的完全控制,不能獨立執行。這意味著這些“線程” 實際上應屬于主線程的子線程。另外,這些子線程并沒有執行I/O操作的權限,只能為主線程分擔一些諸如計算等任務。所以嚴格來講這些線程并沒有完整的功能,也因此這項技術并非改變了javascript語言的單線程本質。

2. 事件循環(EventLoop)


既然js是單線程,那么意味著,當先我們執行一個任務,什么事都干不了,只能等待他執行完。 這是設計者意識到,只是主線程完全可以不考慮IO設備,掛起處于等待中的任務,先運行排在后面的任務,等IO設備返回了結果,再回頭把掛起的設備執行完。

于是所有任務分為兩種: 同步任務異步任務

當javascript代碼執行的時候會將不同的變量存于內存中的不同位置:堆(heap)和棧(stack)中來加以區分,heap中一般存儲我們的變量,stack一般存儲函數或者方法。stack叫做執行棧,我們的方法依次會在這里執行。執行棧事件先進后出,任務隊列先進先出。web apis則是代表一些異步事件,而callback queue即事件隊列。

對照圖片我們解釋一下整個事件循環機制

  • 執行棧執行主線程任務,當有操作domajax交互使用定時器異步操作的時候,這些任務會被移入到 callback queue 任務隊列中
  • 當主線程任務執行完畢為空時,會讀取callback queue隊列中的函數,進入主線程執行
  • 上述過程會不斷重復,也就是常說的Event Loop(事件循環)。

2.1 .macro task與micro task

不同的異步任務被分為兩類:微任務(micro task)和宏任務(macro task)。

在一個事件循環中,異步事件返回結果后會被放到一個任務隊列中。然而,根據這個異步事件的類型,這個事件實際上會被對應的宏任務隊列或者微任務隊列中去,當執行棧為空的時候,主線程會首先查看微任務中的事件,如果微任務不是空的那么執行微任務中的事件,如果沒有在宏任務中取出最前面的一個事件。把對應的回調加入當前執行棧...如此反復,進入循環。

  • macro-task(宏任務)
    • setTimeout
    • setInterval
    • setImmediate
  • micro-task(微任務)
    • Promise
    • process.nextTick
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。