溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JS前端宏任務微任務及Event?Loop如何使用

發(fā)布時間:2022-07-21 09:57:00 來源:億速云 閱讀:141 作者:iii 欄目:開發(fā)技術

這篇文章主要介紹“JS前端宏任務微任務及Event Loop如何使用”,在日常操作中,相信很多人在JS前端宏任務微任務及Event Loop如何使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JS前端宏任務微任務及Event Loop如何使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

前言

首先我們要了解javascript是一個單線程的腳本語言,也就是說我們在執(zhí)行代碼的過程中不會出現(xiàn)同時進行兩個進程(執(zhí)行兩段代碼)。

Javascript語言將任務的執(zhí)行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。

同步:一個進程在執(zhí)行某個請求的時候,若該請求需要一段時間才能返回信息,那么這個進程將會一直等待下去,直到收到返回信息才繼續(xù)執(zhí)行下去。

異步:進程不需要一直等下去,而是繼續(xù)執(zhí)行下面的操作,不管其他進程的狀態(tài)。當有消息返回時系統(tǒng)會通知進程進行處理,這樣可以提高執(zhí)行的效率。

進程:狹義上,就是正在運行的程序的實例。廣義上,進程是一個具有一定獨立功能的程序關于某個數(shù)據集合的一次運行活動。描述的是CPU在運行指令及加載和保存上下文所需要的時間。

線程:是程序中一個單一的順序控制流程。進程內一個相對獨立的、可調度的執(zhí)行單元,是系統(tǒng)獨立調度和分派CPU的基本單位。指運行中的程序的調度單位。

執(zhí)行棧:V8(谷歌瀏覽器引擎)內部維護出來的一個用來存放函數(shù)的執(zhí)行上下文環(huán)境的一個棧結構。

相信有不少人和我有著一樣的疑惑,既然javascript是單線程的腳本語言,那么他有什么優(yōu)勢呢,為什么不寫成多進程的呢?

  • 單線程不僅可以節(jié)省內存同時也可以節(jié)省上下文切換時間;

  • 不會和渲染線程沖突(如果JS是雙線程的,當頁面渲染線程還在執(zhí)行時,JS已經將渲染頁面的參數(shù)修改,就會導致頁面渲染出現(xiàn)問題)

宏任務

(macro)task,可以理解是每次執(zhí)行棧執(zhí)行的代碼就是一個宏任務(包括每次從事件隊列中獲取一個事件回調并放到執(zhí)行棧中執(zhí)行)。

宏任務隊列

  • I/O

  • UI-rendering (頁面渲染)

  • script

  • setTimeout

  • setInterval

  • setImmediate (node環(huán)境下是,而瀏覽器環(huán)境下不是)

  • requestAnimationFrame (在瀏覽器環(huán)境是,而node環(huán)境不是)

requestAnimationFrame在MDN的定義為,下次頁面重繪前所執(zhí)行的操作,而重繪也是作為宏任務的一個步驟來存在的,且該步驟晚于微任務的執(zhí)行。

微任務

microtask,可以理解是在當前 task 執(zhí)行結束后立即執(zhí)行的任務。也就是說,在當前task任務后,下一個task之前,在渲染之前。

所以它的響應速度相比setTimeout(setTimeout是task)會更快,因為無需等渲染。也就是說,在某一個macrotask執(zhí)行完后,就會將在它執(zhí)行期間產生的所有microtask都執(zhí)行完畢(在渲染前)。

微任務隊列

  • process.nextTick (node環(huán)境下是,而瀏覽器環(huán)境下不是)

  • promise.then

  • MutationObserver (在瀏覽器環(huán)境是,而node環(huán)境不是)

Event-Loop

上面我們講了半天宏任務、微任務等各種任務的執(zhí)行那么vent-Loop到底是個啥?

javascript是一個單進程的語言,同一時間不能處理多個任務,所以什么時候執(zhí)行宏任務什么時候執(zhí)行微任務呢?于是乎我們需要Event Loop-事件循環(huán)機制(計算機系統(tǒng)的一種運作機制)這樣一個判斷邏輯存在。

同步代碼: js為腳本語言,對于同步代碼來說,自上而下進行解釋執(zhí)行。

異步代碼: 對于一個任務,分為多個片段來進行執(zhí)行, 先執(zhí)行一段,如果碰到比較耗時間的操作,比如本地或者網絡io請求。 第一段開始進行io之后,把執(zhí)行權交由其他任務,當io完成后再來執(zhí)行后半段的任務(io操作比較耗時,在系統(tǒng)進行io時,主線程是空閑的)

執(zhí)行順序

1. 首先執(zhí)行同步代碼,這屬于宏任務;

2. 當執(zhí)行完所有的同步代碼后,執(zhí)行棧為空,檢查是否有異步代碼要執(zhí)行;

3. 執(zhí)行微任務;

4. 執(zhí)行完微任務后,有必要的情況下會渲染頁面;

5. 開啟下一輪 Event Loop,執(zhí)行宏任務中的代碼;

代碼在執(zhí)行過程中,遇到異步代碼,會將異步代碼用隊列裝起來(掛起)

實戰(zhàn)出真理,我們用一個????感受一下
console.log('start');          // 1
function foo(){
   console.log('foo');           
}
foo()                          // 2
setTimeout(function() {        //異步代碼中的宏任務,先掛起
   console.log('setTimeout'); // 7
},1000)
new Promise(resolve =>{
   console.log('promise');    // 3
   resolve()
})
   .then(function() {        //異步代碼中的微任務,先掛起
       console.log('promise1');// 5
   })
   .then(function() {        //異步代碼中的微任務,先掛起
       console.log('promise2');// 6
   })
console.log('end');            // 4

我們跟著實行順序來分析,第一步首先執(zhí)行同步代碼,所以首先打印出來‘start’,調用函數(shù)foo打印出來‘foo’,執(zhí)行Promise函數(shù)打印出來‘promise’,最后打印出來‘end’同步代碼就執(zhí)行完畢,再檢查是否有異步代碼要執(zhí)行,第三步執(zhí)行微任務,所以先打印出第一微任務列表中的‘promise1’,緊接著打印第二微任務列表中的‘promise2’純js不用渲染頁面,最后開啟下一輪的Event-Loop,執(zhí)行宏任務中的代碼,而setTimeout就是異步代碼中的宏任務所以最終打印出來‘setTimeout’,最后我們來看看在谷歌瀏覽器中的打印效果。

JS前端宏任務微任務及Event?Loop如何使用

這里有個小細節(jié),如果將定時器setTimeout的時間設置為0呢?結果其實還是一樣的,setTimeout不會因為時間而改變執(zhí)行順序,因為它仍然是異步代碼中的宏任務,不會因為延遲執(zhí)行的時間而改變。

到此,關于“JS前端宏任務微任務及Event Loop如何使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

js
AI