JavaScript語言的一大特色就是單線程,也就是說,同一個時間只能作一件事。那麼,爲何JavaScript不能有多個線程呢?這樣能提升效率啊。javascript
JavaScript的單線程,與它的用途有關。做爲瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操做DOM。這決定了它只能是單線程,不然會帶來很複雜的同步問題。好比,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另外一個線程刪除了這個節點,這時瀏覽器應該以哪一個線程爲準?前端
因此,爲了不復雜性,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特徵,未來也不會改變。java
爲了利用多核CPU的計算能力,HTML5提出Web Worker標準,容許JavaScript腳本建立多個線程,可是子線程徹底受主線程控制,且不得操做DOM。因此,這個新標準並無改變JavaScript單線程的本質。node
參考地址:Event Loop 這個循環你曉得麼?(附 GIF 詳解)-餓了麼前端git
將事件插入到了事件隊列,必須等到當前代碼(執行棧)執行完,主線程纔會去執行它指定的回調函數。
當主線程時間執行過長,沒法保證回調會在事件指定的時間執行。
瀏覽器端每次setTimeout會有4ms的延遲,當連續執行多個setTimeout,有可能會阻塞進程,形成性能問題。github
事件插入到事件隊列尾部,主線程和事件隊列的函數執行完成以後當即執行。和setTimeout(fn,0)的效果差很少。
服務端node提供的方法。瀏覽器端最新的api也有相似實現:window.setImmediate,但支持的瀏覽器不多。編程
插入到事件隊列尾部,但在下次事件隊列以前會執行。也就是說,它指定的任務老是發生在全部異步任務以前,當前主線程的末尾。
大體流程:當前」執行棧」的尾部–>下一次Event Loop(主線程讀取」任務隊列」)以前–>觸發process指定的回調函數。
服務器端node提供的辦法。用此方法能夠用於處於異步延遲的問題。
能夠理解爲:這次不行,預定下次優先執行。api
Promise自己是同步的當即執行函數, 當在 executor 中執行 resolve 或者 reject 的時候, 此時是異步操做, 會先執行 then/catch 等,當主棧完成後,纔會去調用 resolve/reject 中存放的方法執行,打印 p 的時候,是打印的返回結果,一個 Promise 實例。promise
Async/Await就是一個自執行的generate函數。利用generate函數的特性把異步的代碼寫成「同步」的形式。瀏覽器
async 函數返回一個 Promise 對象,當函數執行的時候,一旦遇到 await 就會先返回,等到觸發的異步操做完成,再執行函數體內後面的語句。能夠理解爲,是讓出了線程,跳出了 async 函數體。