Javascript異步機制

Javascript做爲一種單線程語言,是如何實現異步編程的呢?javascript

相信很多人對Javascript單線程表示懷疑:爲什麼單線程能夠實現異步操做呢?其實Javascript確實是單線程的(咱們不妨把這個線程稱做主線程),但它實現異步操做的方式確實藉助了瀏覽器的其餘線程的幫助。那其餘線程是怎麼幫助Javascript主線程來實現異步的呢?答案就是任務隊列(task queue)和事件循環(event loop)。java

任務隊列

首先,做爲單線程語言,在Javascript中定義的任務都會在主線程中執行。可是並非每一個任務都會馬上執行,而這種不馬上執行的任務咱們稱做異步任務。相反,那些馬上執行的任務咱們把它們稱做同步任務。而這些異步任務都會交給瀏覽器的其餘線程去執行,可是主線程須要瞭解這些異步任務執行的狀態,才方便進行下一步操做。編程

打個比方,主線程準備作飯,因此下達一個異步任務去買菜,異步任務買完菜以後得告訴主線程:「我買完菜啦」,這個時候主線程纔好開始作飯。瀏覽器

而咱們知道由於Javascript是單線程,因此上述的「下一步操做」無法直接定義在主函數裏(否則就被當作同步任務直接執行了),那這些應該定義在哪裏呢?答案就是異步任務的回調函數中。在Javascript異步機制中,任務隊列就是用來維護異步任務回調函數的隊列。這樣一個隊列用來存放這些回調函數,它們會等到主線程執行完全部的同步函數以後按照先進先出的方式挨個執行。那麼執行完任務隊列以後呢?Javascript主線程就執行完畢了嗎?固然不是,否則網頁加載完畢以後,誰來處理後續與用戶的交互事件(好比點擊事件)呢?異步

事件循環

javascript_asyc.jpg
咱們經過上圖來更加形象的瞭解Javascript的異步機制。
執行同步任務 -> 檢查任務隊列中是否有任務 -> [有若是則執行] -> 檢查任務隊列中是否有任務 -> [有若是則執行] -> ......
可見主線程在執行完同步任務以後,會無限循環地去檢查任務隊列中是否有新的「任務」,若是有則執行。而這些任務包括咱們在異步任務中定義的回調函數,也包括用戶交互事件的回調函數。經過事件循環,Javascript不只很好的處理了異步任務,也很好的完成了與用戶交互事件的處理。由於在完成異步任務的回調函數以後,任務隊列中的任務都是由事件所產生的,所以咱們也把上述的循環過程叫作事件循環異步編程

異步機制實踐

console.log('定時器去買菜吧')
setTimeout(function(){
    console.log('菜買完了,主線程去作菜吧')
}, 0)
console.log('你先去買菜,我先看個世界盃')

在瀏覽器中執行上述代碼,興許能更好地理解Javascript的異步機制。函數

總結

總而言之,Javascript單線程的背後有瀏覽器的其餘線程爲其完成異步服務,這些異步任務爲了和主線程通訊,經過將回調函數推入到任務隊列等待執行。主線程所作的就是執行完同步任務後,經過事件循環,不斷地檢查並執行任務隊列中回調函數。oop

相關文章
相關標籤/搜索