這段參考了參考來源中的第2篇文章(英文版的),(加了下本身的理解從新描述了下),前端
這裏無法給你們演示代碼,我就簡單說下個人理解吧。node
promise和settimeout 在一塊兒的時候執行順序是個有意思的事兒,promise
爲何呢?由於Promise裏有了一個一個新的概念:microtask
瀏覽器
或者,進一步,JS中分爲兩種任務類型:macrotask
和microtask
,在ECMAScript中,microtask稱爲jobs
,macrotask可稱爲task
微信
它們的定義?區別?簡單點能夠按以下理解:多線程
macrotask(又稱之爲宏任務),能夠理解是每次執行棧執行的代碼就是一個宏任務(包括每次從事件隊列中獲取一個事件回調並放到執行棧中執行)學習
每個task會從頭至尾將這個任務執行完畢,不會執行其它線程
瀏覽器爲了可以使得JS內部task與DOM任務可以有序的執行,會在一個task執行結束後,在下一個 task 執行開始前,對頁面進行從新渲染
code
(`task->渲染->task->...`)
microtask(又稱爲微任務),能夠理解是在當前 task 執行結束後當即執行的任務隊列
也就是說,在當前task任務後,下一個task以前,在渲染以前
因此它的響應速度相比setTimeout(setTimeout是task)會更快,由於無需等渲染
也就是說,在某一個macrotask執行完後,就會將在它執行期間產生的全部microtask都執行完畢(在渲染前)
分別很麼樣的場景會造成macrotask和microtask呢?
macrotask:主代碼塊,setTimeout,setInterval等(能夠看到,事件隊列中的每個事件都是一個macrotask)
microtask:Promise,process.nextTick等
__補充:在node環境下,process.nextTick的優先級高於Promise__,也就是能夠簡單理解爲:在宏任務結束後會先執行微任務隊列中的nextTickQueue部分,而後纔會執行微任務中的Promise部分。
再根據線程來理解下:
macrotask中的事件都是放在一個事件隊列中的,而這個隊列由事件觸發線程維護
microtask中的全部微任務都是添加到微任務隊列(Job Queues)中,等待當前macrotask執行完畢後執行,而這個隊列由JS引擎線程維護(這點由本身理解+推測得出,由於它是在主線程下無縫執行的)
因此,總結下運行機制:
執行一個宏任務(棧中沒有就從事件隊列中獲取)
執行過程當中若是遇到微任務,就將它添加到微任務的任務隊列中
宏任務執行完畢後,當即執行當前微任務隊列中的全部微任務(依次執行)
當前宏任務執行完畢,開始檢查渲染,而後GUI線程接管渲染
渲染完畢後,JS線程繼續接管,開始下一個宏任務(從事件隊列中獲取)
另外,請注意下Promise
的polyfill
與官方版本的區別:
官方版本中,是標準的microtask形式
polyfill,通常都是經過setTimeout模擬的,因此是macrotask形式
請特別注意這兩點區別
注意,有一些瀏覽器執行結果不同(由於它們可能把microtask當成macrotask來執行了),
可是爲了簡單,這裏不描述一些不標準的瀏覽器下的場景(但記住,有些瀏覽器可能並不標準)
好了,到這裏我們這個從瀏覽器到多進程到多線程到js單線程到js運行機制就講完了。內容還算是比較全面,不足的就是隻能聽麼有代碼參考。
不過不要緊,你們能夠根據我提到的知識點本身再進行深刻的學習,或者關注下我我的的公衆號-重度前端,我講的內容都有文字版在上面並且有代碼,另外我記錄了一些我平時看到的比較好的 有深度的文章,還有一些原創內容。直接微信 搜 重度前端。
好了,今天就到這裏了。後面計劃下分享哪些有意思的東西,我們下次見。