看了多篇關於js事件循環機制解讀的博文,知識點很多,作個筆記。對於本身而言好記性不如爛筆頭嘛~(╹▽╹)。不想看的能夠擼到底部看看大佬們寫得優質博文呦~javascript
先看個簡單的代碼:html
console.log('a')
setTimeout(() => {
console.log('b')
}, 0)
console.log('c')
// 輸出 a c b
複製代碼
爲何呢?首先你得明白最重要的一點是:js是單線程的!java
單線程就意味着一次只能幹一件事,其它的任務都得按順序,都要排隊!下一任務必須等上一個任務執行完才能執行;若是上一個任務執行時間很長那下一個任務就得一直等着。emmm這不明顯是搞事情嘛(# ̄~ ̄#)。就很煩! 這就會形成CPU利用率不高,不少時候CPU是閒着沒事幹的;JavaScript設計者固然也知道啊;因而任務就分紅了**‘同步’和‘異步’**兩種。也就有了事件循環機制(Event Loop)。git
事件循環機制以下:github
上面setTimeout是異步的,因此回調會在最後執行。數據庫
如今來看個稍微複雜一丟丟的代碼:promise
setTimeout(() => {
console.log(1)
setTimeout(() => {
console.log(4)
},0)
},0)
console.log(2)
new Promise((resolve, reject) => {
console.log(5)
resolve()
}).then(() => {
console.log(6)
})
console.log(3)
// 輸出 2 5 3 6 1 4
複製代碼
你可能會疑惑爲何promise.then的回調要比setTimeout的先執行呢?瀏覽器
這就涉及到宏任務(macrotask)
和微任務(microtask)
的知識點了。bash
宏任務和微任務都是異步任務,都屬於異步任務隊列。區別在於它們的執行順序不一樣。 對於什麼是macrotask,什麼是microtas,這裏不作解釋,本身能夠查閱理解。異步
如下是關於哪些是macrotask,哪些是microtask
的總結
常見的macrotask任務源有如下幾種:
通常microtask 包括
關於macrotask(task)和microtask執行的總結
每一個 eventloop 由三個階段構成:執行一個 task,執行 microtask 隊列,可選的 ui render 階段,
tasks按序執行,瀏覽器會在 tasks 之間執行ui渲染。
microtasks 按序執行,在下面狀況時執行:
1 、microtask 執行時機『儘量早』,只要 javascript 執行棧爲空,就會執 行。即在每一個回調以後,只要沒有其它代碼正在運行。一輪 eventloop 中,可能執行屢次 microtask
二、在每一個 task 的末尾(同一次事件循環中, 微任務永遠在宏任務以前執行。)
Promise.then爲微任務,因此在主線程執行完後會當即執行,微任務執行完才執行下一個task(setTimeout)
setTimeout是每過n秒
會執行一次,而setInterval每n秒
就會執行一次。聽起來有點繞,結合js eventLoop就能更好理解。setInterval每n秒就會往異步隊列裏注入回調函數,若是有一個回調函數執行時間很長,此時隊列已有多個回調,然後續這些回調執行有很快,那麼從這些回調的執行結果來看就有可能看不出有時間間隔。而setTimeout是過n秒後,纔會有異步回調任務。 之前知道,但對於這不是理解很透徹,如今明白嗎emmm...o( ̄︶ ̄)o,就很棒! 可能我說的不是很清楚,本身能夠多多查找資料,理解理解~
其它一些零碎的知識點
setTimeout(fn, 0):有時咱們用這種方法讓代碼延遲執行。置於爲何,相信你理解了js的eventLoop以後也就明白了。這裏要說的是設置的0秒實際是達不到的,由於html標準最低是4ms。 關於16.7ms的問題:主流的屏幕刷新率都在60hz,即1秒60幀,好比動畫看起來要流暢不掉幀,此時得在16.7ms內渲染完成才能不掉幀,因此時間間隔爲16.7ms會比較合適
PS:本人比較少寫文章,不足之處多多諒解,有錯的地方歡迎指正。
資料來源:
JavaScript 運行機制詳解:再談Event Loop