小葵花課堂又開課了驚不驚喜,意不意外,今天扯扯js的非同步機制,這個非同步機制,就像藏在面紗後面的大姑娘,扯下面紗那一剎那定眼一看也就那麼回事,只要用心看一下,這玩意簡單的不能再簡單,我希望能用最簡單的話給大夥描述明白它到底是個咋雞兒回事
按照國際慣例還是要提出問題,有了問題才更好理解:
- 啥叫非同步
- 為啥要非同步
- 為啥要了解非同步機制
有點基礎的都知道js單執行緒,非同步可以防止阻塞,基礎問題就不多贅述了,重點就是我們為啥要了解非同步機制,個人認為有兩個方面:
- 一是在平常寫程式碼時候容易碰到一些執行順序的坑,雖說一般不會引起什麼太大問題,但是當程式複雜龐大後,一旦有因為程式執行順序引起的問題很難被發現。
- 二是我們在做效能優化時有可能會用到相關知識,畢竟微任務要比巨集任務執行的快點,,類似這些雞毛蒜皮的破事,日常開發中大家都家大業大的誰會在乎這點效能。如果你要寫個牛逼的庫或外掛那這事你就得深入研究研究了“錢”也還都是省出來的。
啊扯那去了,我都不知道我要寫啥了,唱首歌壓壓驚
js的非同步實現得分兩個方向來說,一個是瀏覽器的實現,另一個是node.js的實現 我們先說瀏覽器的:
說之前插播點題外話,這裡邊有兩個概念,大學時候學過資料結構的很好理解,就是 棧 ,佇列,棧遵從先進後出的原則,佇列可以理解成排隊,不懂的我們就不去糾結他是啥,就記住這倆名字就成,就當是兩個容器
- Row No.1 程式碼在棧裡一次執行
- Row No.2 碰到非同步程式碼執行,瀏覽器等著執行完將回撥放在佇列中
- Row No.3 瀏覽器會有個迴圈,棧裡的程式碼執行完了將佇列中程式碼都拿出來放入棧裡在執行
我都懶得畫圖,就這麼簡單,上面過程不停迴圈,就是瀏覽器的非同步機制Event Loop!
執行完同步程式碼,將非同步執行完的回撥程式碼拿出來放到棧在依次執行一遍!不停的迴圈這個過程,直到js程式碼全部執行完!
後來這裡面插入了微任務的概念,意思就是說,有些東西我不想馬上執行,但是也不想排在非同步佇列後面,就是執行完當前同步程式碼,馬上就執行這個任務,這就叫微任務,任務存在微任務佇列裡,那相對的原先那個非同步佇列就叫巨集任務
微任務是每次執行完同步程式碼立即就執行微任務,然後再去檢索巨集任務去執行
然而Node的事件環和瀏覽器有啥區別呢?下圖是個node事件環模型
看圖雖然複雜,但是我們只需要關心timers計時器階段,poll輪詢階段,check檢查階段(setImmediate回掉),clons關閉階段以及微任務佇列即可,因為處理網路,內部呼叫與我們們的巨集任務和微任務的執行沒有太大的關係 和瀏覽器執行環境不同的是微任務只會在階段轉化的時候才會呼叫,就是close關閉階段後再執行下一階段的時候 如果巨集任務執行的時候又發現微任務了,不會和瀏覽器一樣順便執行了,而是會將微任務再放到微任務佇列中,等待整個階段結束後,下一個階段開始的時候先執行完微任務佇列中的微任務
就這麼簡單。。。。