Javascript 之 Event Driven
javascript
Lastmod: 2019-12-13

Javascript單線程該篇文章中有提到,大部份這種單線程但可以處理非同步的語言都有共同的特性那就是事件驅動(Event Driven),它一般是由通過事件循環(Event Loop)事件隊列(Event Queue)來實現。

事件驅動 ( Event Driven ) 與事件隊列( Event Queue )

先來說說事件驅動(Event Driven),這種類型的程式執行流程基本上是由使用者的動作例如點擊了頁面或按了ENTER之類的事件來決定,而不像一些如批次程式設計(batch programming)是由程式開發者來決定。

我們來看看下面這張Philip Roberts在JSConf EU 2014講述Javascript event-loop時所出現的這圖。

eventloop.png

首先左上角為V8 Javascript runtime,其中裡面的Stack代表JS接下來要做的事情(嚴格來說要做的任務被分配到的記憶體空間)由上至下來執行。Philip Roberts在演講中也有提到因javascript單線程而所擁有的等式。

one thread == one call stack == on thing at time

其中Stack裡面的工作有些是非同步事件,例如ajax或settimeout等,stack會將工作丟給WebApis該區塊進行(嚴格來說是v8中某個東西會丟),等到執行完後成,會發送個callback給callbackQueue,等到Stack完全清空時,會至callback queue裡尋找看看有沒有callback要執行。

Javascript程式碼單線程運行流程範例

我們將以下列這段簡單的程式碼來看Javascript的執行流程。

	console.log("hi")
	setTimeout(function cb(){
		console.log("there");
	},5000);
	console.log("Mark Lin");

首先為第一張圖,在還沒執行程式程式碼時,所有的StackTask Quenu都是空的。 ScreenClip.png

然後我們開始執行,首先載入這段JS,Stack會產生main()這個區塊,再執行到 console.log('hi')時,也會在Stack產生console.log('hi')的區塊,並在Console印出hi,最後console.log('hi')工作完成,會從Stack中釋放出。

ScreenClip.png

執行到setTimeooutStack會產生setTimeout的區塊,並且會向api發送工作,然後繼續往下執行。

ScreenClip.png

執行console.log("Mark Lin"),最後工作剛成後,Stack全部清空。

ScreenClip.png

Stack全部空間釋放完後,同時也發現剛剛對api的請求已完成,並且已將CallBack cb放置Task Quenu,並且由於Stack已清空,它會自動去Task Quenu尋找Task,這時發現了Cb然後就執行consoel.log("there")

ScreenClip.png

參考資料

comments powered by Disqus