Javascript Event Loop 線程模型

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

爲了更好地理解Event Loop,請看下圖(轉引自Philip Roberts的演講《Help, I'm stuck in an event-loop》)。java

輸入圖片說明

上圖中,主線程運行的時候,產生堆(heap)和棧(stack),棧中的代碼調用各類外部API,它們在"任務隊列"中加入各類事件(click,load,done)。只要棧中的代碼執行完畢,主線程就會去讀取"任務隊列",依次執行那些事件所對應的回調函數。 執行棧中的代碼(同步任務),老是在讀取"任務隊列"(異步任務)以前執行。請看下面這個例子。api

var req = new XMLHttpRequest();
    req.open('GET', url);    
    req.onload = function (){};    
    req.onerror = function (){};    
    req.send();

上面代碼中的req.send方法是Ajax操做向服務器發送數據,它是一個異步任務,意味着只有當前腳本的全部代碼執行完,系統纔會去讀取"任務隊列"。因此,它與下面的寫法等價。瀏覽器

var req = new XMLHttpRequest();
    req.open('GET', url);
    req.send();
    req.onload = function (){};    
    req.onerror = function (){};

也就是說,指定回調函數的部分(onload和onerror),在send()方法的前面或後面可有可無,由於它們屬於執行棧的一部分,系統老是執行完它們,纔會去讀取"任務隊列"。服務器

以前就有疑問javascript是單線程執行的,那麼他怎麼作異步呢?異步至少2個線程吧?其實根據上圖,js調用了瀏覽器的api,讓瀏覽器中的進程去作任務,js本身的線程通知瀏覽器api後繼續向下執行本身的代碼。瀏覽器api執行完後將結果放入隊列中,js執行完本身的同步代碼後,啓動event loop 從隊列中調用結果放入堆棧執行。異步

相關文章
相關標籤/搜索