JavaScript 事件循環

js是一門單線程的語言,不可能進行多線程編程,異步編程就是多線程編程一種模式,但是我們經常講到js的異步編程,其實是偽異步,因為它是單線程的,也就是同步,只有前面的代碼執行完才能執行下面的代碼。所以要理解js中的異步理念,就需要了解js的運行核心--

事件循環(Event loop)

JavaScript 事件循環

為什麼js會有異步呢

setTimeout(function(){ //5秒之後執行程序 },5000)

我們想象一下,在同步的執行上面的代碼,需要等待5秒才能執行定時器中的程序,然後在往下執行,在這5秒的過程中,瀏覽器沒有任何反應,出現了阻塞,在用戶體驗上很不好。所以異步的模式就出現,為了解決瀏覽器非阻塞的運行。

單線程如何做到異步

js的任務分為同步異步兩種,它們的處理方式也不同,同步任務是直接在主線程上排隊執行,異步任務則會被放到事件隊列中,若有多個異步任務則要在事件隊列中排隊等待,事件隊列類似一個緩衝區,任務下一步會被移到調用棧,然後主線程執行調用棧的任務。

單線程是指js引擎中負責解析執行js代碼的線程只有一個主線程,即每次只能做一件事,而我們知道一個ajax請求,主線程在等待它響應的同時是會去做其它事的,瀏覽器先在事件表註冊ajax的回調函數,響應回來後回調函數被添加到任務隊列中等待執行,不會造成線程阻塞,所以說js處理ajax請求的方式是異步的。

總而言之,檢查調用棧是否為空,以及確定把哪個異步任務加入調用棧的這個過程就是事件循環,而js實現異步的核心就是事件循環。

一次事件循環的步驟包括:

  1. 主線程在執行代碼的時候,遇到異步任務會將它添加到一個事件隊列中(可以理解為一個數組),然後繼續執行下面的代碼,直到同步代碼執行完,然後執行步驟2

  2. 檢查事件隊列是否為空,非空執行步驟3,為空則繼續執行步驟2

  3. 取出事件隊列中的第一個放到調用棧,然後主線程執行調用棧的任務,再執行步驟4

  4. 執行視圖更新,然後回到步驟2

這就是事件循環

先看一段代碼,理解一下:(面試題哦)

console.log('start')setTimeout(function() { console.log('setTimeout')}, 0)Promise.resolve().then(function() { console.log('promise1')}).then(function() { console.log('promise2')})console.log('end')

打印臺輸出的log順序是什麼?結合上面的步驟分析一下

JavaScript 事件循環

最後的結果是:

startendpromise1pormise2setTimeout


分享到:


相關文章: