- 做者:陳大魚頭
- github: KRISACHAN
- 連接:github.com/YvetteLau/S…
- 背景:最近高級前端工程師 劉小夕 在 github 上開了個每一個工做日佈一個前端相關題的 repo,懷着學習的心態我也參與其中,如下爲個人回答,若是有不對的地方,很是歡迎各位指出。
相信你們常常會聽到一句話,就是 「JS是單線程的」,但是什麼是 線程,什麼又是 單線程,有 多線程 嗎?javascript
講到線程,那麼確定也得說一下進程。其實在本質上,兩個名詞都是 CPU 工做時間片的一個描述。前端
進程(process) 指的是CPU 在 運行指令及加載和保存上下文所需的時間,放在應用上是指計算機中已運行的程序。java
線程(thread) 是操做系統可以進行運算的最小單位。它被包含在 進程 之中,描述了執行一段指令所需的時間。node
瀏覽器中的線程分了如下幾類:git
執行棧能夠理解爲是用來存儲函數調用的棧,遵循先進後出的原則。github
Node 的 Event Loop 分爲 6 個階段,它們會按照順序反覆運行。每當進入某一個階段的時候,都會從對應的回調隊列中取出函數去執行。當隊列爲空或者執行的回調函數數量到達系統設定的閾值,就會進入下一階段。promise
Event Loop 6 個階段:瀏覽器
瀏覽器端 的狀況與 node端 的狀況相仿,當咱們執行 JS 代碼的時候其實就是往執行棧中放入函數,當遇到異步的代碼時,會被掛起並在須要執行的時候加入到 Task(有多種 Task) 隊列中。一旦執行棧爲空,Event Loop 就會從 Task 隊列中拿出須要執行的代碼並放入執行棧中執行。微信
執行順序以下:前端工程師
上面講了定時器是屬於 宏任務(macrotask) 。若是當前 執行棧 所花費的時間大於 定時器 時間,那麼定時器的回調在 宏任務(macrotask) 裏,來不及去調用,全部這個時間會有偏差。
咱們看如下代碼:
setTimeout(function () {
console.log('biubiu');
}, 1000);
某個執行時間很長的函數();
複製代碼
若是定時器下面的函數執行要 5秒鐘,那麼定時器裏的log 則須要 5秒以後再執行,函數佔用了當前 執行棧 ,要等執行棧執行完畢後再去讀取 微任務(microtask),等 微任務(microtask) 完成,這個時候纔會去讀取 宏任務(macrotask) 裏面的 setTimeout 回調函數執行。setInterval 同理,例如每3秒放入宏任務,也要等到執行棧的完成。
還有一種狀況以下:
setTimeout(function() {
setTimeout(function() {
setTimeout(function() {
setTimeout(function() {
setTimeout(function() {
setTimeout(function() {
console.log('嚶嚶嚶');
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
}, 0);
複製代碼
在最新的規範裏有這麼一句: If nesting level is greater than 5, and timeout is less than 4, then increase timeout to 4.
因此意思就是意思就是若是timeout嵌套大於 5層,而時間間隔小於4ms,則時間間隔增長到4ms。