從咱們第一天接觸js的時候咱們就知道js是單線程的,且js是異步的,首先來看一下基本概念javascript
線程是操做系統可以進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運做單位。(百度百科)
css
舉個最簡單的例子 , 在咱們電腦的任務管理器中你打開一個應用程序的時候 就會多一個進程,他表明了cpu能處理的單個任務。html
線程是進程下的執行者,一個進程至少會開啓一個線程(主線程),也能夠開啓多個線程,好比你打開了一個vscode編輯器,裏邊你能作的操做會有不少好比cmd node 等等前端
js是運行在瀏覽器的,是由js引擎解析和執行的,那麼咱們先了解一下瀏覽器都有哪些線程
首先要說明的是 瀏覽器是多線程的java
Browser進程:瀏覽器的主進程node
第三方插件進程web
GPU進程ajax
瀏覽器渲染進程數據庫
對於前端來說這些進程中最重要的是瀏覽器渲染進程,也被稱之爲是瀏覽器內核,由於咱們的頁面渲染,事件等等都在這個進程中進行的promise
瀏覽器的渲染進程裏邊有一些常駐的線程好比說
因此說若是咱們頁面在一開始js文件須要計算或者操做的時間比較長的時候,會出現大段時間的白屏,
由於js引擎在執行的時候會使頁面渲染堵塞,若是dom發生更新的時候,gui更新會被存在一個隊列裏邊,等到js引擎空閒的時候纔會被執行
一個tab頁裏邊不管如何都只有一個js線程,就算是後來的webworker ,他也是隻屬於js引擎的一個子類,而且它不能操做dom
忽然以爲js引擎好累,什麼都是要他去作,爲何不設計成多線程,從網上其餘地方看了的答案,大同小異,講的是多線程操做dom有可能會同時操做一個dom發生錯誤云云
說完了上邊的一些概念,你也應該大致的瞭解了js的單線程這個問題
下邊從js引擎的一些運行機制說一說js的異步
剛纔已經講了,瀏覽器中不只有js引擎線程還有其餘,異步的話主要會用到事件觸發線程和定是觸發器線程的概念
在js中氛圍同步任務和異步任務 ,全部的同步任務都會在主線程上執行,造成一個執行棧(先進後出)
在主線程以外還有一個異步的事件隊列
在執行棧執行完畢以後,也就是同步任務執行完畢以後,js引擎線程就會去輪詢事件隊列,看有沒有須要執行的事件,有的話就會執行事件隊列的事件
我記得我最開始的時候使用ajax 或者數據庫查詢的時候遇到過這麼一個狀況,在作完操做以後就天真的認爲能夠用返回的值,結果當時我被異步搞得裏焦外嫩,甚至我覺得在發送完請求以後多作一些操做等一會請求,請求值就會返回來,結果。。。
其實否則, 在同一個事件循環內部,不管作多少操做,你的異步操做只會在執行棧執行完畢以後纔會被執行
同時異步也是有優先級的,在事件循環裏邊js的任務類型分爲兩種
宏任務就是說執行棧裏的每個被執行的代碼就是一個宏任務,包括一個事件產生的回調執行
宏任務會在執行完畢一段代碼以後先對dom進行一次渲染,而後再執行下一個宏任務
微任務是再宏任務執行完畢以後當即執行的,他在dom從新渲染以前,
因此微任務的相應速度比宏任務是要快的
像 定時器,延時器 主代碼塊等等就是一個宏任務,promise nextTick等就是微任務
正常在延時器打印和在promise裏邊打印,promise的打印是會比延時器的先打印的
因此總結一下js的運行機制是
以上有說的不對或者不足之處,請批評指正