摘要:而當(dāng)響應(yīng)成功了以后,瀏覽器的事件表則會(huì)將回調(diào)函數(shù)添加至事件隊(duì)列中等待執(zhí)行。事件循環(huán)器會(huì)不停的檢查事件隊(duì)列,如果不為空,則取出隊(duì)首壓入執(zhí)行棧執(zhí)行。類型的任務(wù)目前包括了以及的回調(diào)函數(shù)。
事件循環(huán)(event loop) :
首先說事件隊(duì)列(task queue)
事件隊(duì)列是一個(gè)存儲(chǔ)著待執(zhí)行任務(wù)的隊(duì)列,其中的任務(wù)嚴(yán)格按照時(shí)間先后順序執(zhí)行,排在隊(duì)頭的任務(wù)將會(huì)率先執(zhí)行,而排在隊(duì)尾的任務(wù)會(huì)最后執(zhí)行。
事件隊(duì)列每次僅執(zhí)行一個(gè)任務(wù),在該任務(wù)執(zhí)行完畢之后,再執(zhí)行下一個(gè)任務(wù)。
執(zhí)行棧則是一個(gè)類似于函數(shù)調(diào)用棧的運(yùn)行容器,當(dāng)執(zhí)行棧為空時(shí),JS 引擎便檢查事件隊(duì)列,如果不為空的話,事件隊(duì)列便將第一個(gè)任務(wù)壓入執(zhí)行棧中運(yùn)行。
當(dāng)我們設(shè)置一個(gè)延遲函數(shù)的時(shí)候,當(dāng)前腳本并不會(huì)阻塞,它只是會(huì)在瀏覽器的事件表中進(jìn)行記錄,程序會(huì)繼續(xù)向下執(zhí)行。 當(dāng)延遲的時(shí)間結(jié)束之后,事件表會(huì)將回調(diào)函數(shù)添加至事件隊(duì)列中,事件隊(duì)列拿到了任務(wù)過后便將任務(wù)壓入執(zhí)行棧(stack)當(dāng)中,執(zhí)行棧執(zhí)行任務(wù)
事件循環(huán)機(jī)制:
檢查事件隊(duì)列是否為空,如果為空,則繼續(xù)檢查;如不為空,則執(zhí)行 2;
取出事件隊(duì)列的首部,壓入執(zhí)行棧;
執(zhí)行任務(wù)
檢查執(zhí)行棧,如果執(zhí)行棧為空,則跳回第 1 步;如不為空,則繼續(xù)檢查;
結(jié)合 Web APIs 事件循環(huán):
ajax 請求掛起,然后繼續(xù)執(zhí)行后面的代碼,至于請求何時(shí)響應(yīng),對我們的程序不會(huì)有影響,甚至它可能永遠(yuǎn)也不響應(yīng),也不會(huì)使瀏覽器阻塞。
而當(dāng)響應(yīng)成功了以后,瀏覽器的事件表則會(huì)將回調(diào)函數(shù)添加至事件隊(duì)列中等待執(zhí)行。
事件監(jiān)聽器的回調(diào)函數(shù)也是一個(gè)任務(wù),當(dāng)我們注冊了一個(gè)事件監(jiān)聽器時(shí),瀏覽器事件表會(huì)進(jìn)行登記,當(dāng)我們觸發(fā)事件時(shí),事件表便將回調(diào)函數(shù)添加至事件隊(duì)列當(dāng)中。
事件循環(huán)器會(huì)不停的檢查事件隊(duì)列,如果不為空,則取出隊(duì)首壓入執(zhí)行棧執(zhí)行。當(dāng)一個(gè)任務(wù)執(zhí)行完畢之后,事件循環(huán)器又會(huì)繼續(xù)不停的檢查事件隊(duì)列,
不過在這間,任務(wù)結(jié)束后瀏覽器會(huì)對頁面進(jìn)行渲染。這就保證了用戶在瀏覽頁面的時(shí)候不會(huì)出現(xiàn)頁面阻塞的情況,這也使 JS 動(dòng)畫成為可能,同步就沒動(dòng)畫的漸變效果了。
總結(jié):
事件隊(duì)列嚴(yán)格按照時(shí)間先后順序?qū)⑷蝿?wù)壓入執(zhí)行棧執(zhí)行;
當(dāng)執(zhí)行棧為空時(shí),瀏覽器會(huì)一直不停的檢查事件隊(duì)列,如果不為空,則取出第一個(gè)任務(wù);
在每一個(gè)任務(wù)結(jié)束之后,瀏覽器會(huì)對頁面進(jìn)行渲染;
- 接下來說一下不同的任務(wù)(task)之間的執(zhí)行順序問題
microtask
每一個(gè) 事件循環(huán)(event loop)都有著眾多不同的任務(wù)來源(task source),這些來源能夠保證其中的任務(wù)能夠有序的執(zhí)行。不過,在每一輪事件循環(huán)結(jié)束之后,瀏覽器可以自行選擇將哪一個(gè)來源當(dāng)中的任務(wù)加入到執(zhí)行隊(duì)列當(dāng)中
任務(wù)Task是嚴(yán)格按照時(shí)間順序 壓棧和執(zhí)行 的,當(dāng)一個(gè) task 執(zhí)行結(jié)束后,在下一個(gè) task 執(zhí)行開始前,瀏覽器可以對頁面進(jìn)行重新渲染
Microtask 通常來說就是需要在當(dāng)前 task 執(zhí)行結(jié)束后立即執(zhí)行的任務(wù),
例如需要對一系列的任務(wù)做出回應(yīng),或者是需要異步的執(zhí)行任務(wù)而又不需要分配一個(gè)新的 task,這樣便可以減小一點(diǎn)性能的開銷。microtask
任務(wù)隊(duì)列是一個(gè)與 task 任務(wù)隊(duì)列相互獨(dú)立的隊(duì)列, microtask 任務(wù)將會(huì)在每一個(gè) task 任務(wù)執(zhí)行結(jié)束之后執(zhí)行。每一個(gè)
task 中產(chǎn)生的 microtask 都將會(huì)添加到 microtask 隊(duì)列中, microtask 中產(chǎn)生的 microtask
將會(huì)添加至當(dāng)前隊(duì)列的尾部,并且 microtask 會(huì)按序的處理完隊(duì)列中的所有任務(wù)。 microtask 類型的任務(wù)目前包括了
MutationObserver 以及 Promise 的回調(diào)函數(shù)。 microtask 執(zhí)行在當(dāng)前 task 結(jié)束之后,下一個(gè) task 開始之前。
microtask 執(zhí)行在當(dāng)前 task 結(jié)束之后,下一個(gè) task 開始之前。
另外補(bǔ)充一下上文說到的 Mutation Observer
使用鏈接見文章: https://segmentfault.com/a/11...
Mutation Observer API 用來監(jiān)視 DOM 變動(dòng)。DOM 的任何變動(dòng),比如節(jié)點(diǎn)的增減、屬性的變動(dòng)、文本內(nèi)容的變動(dòng),這個(gè) API 都可以得到通知。 它等待所有腳本任務(wù)完成后,才會(huì)運(yùn)行(即異步觸發(fā)方式)。 它把 DOM 變動(dòng)記錄封裝成一個(gè)數(shù)組進(jìn)行處理,而不是一條條個(gè)別處理 DOM 變動(dòng)。 它既可以觀察 DOM 的所有類型變動(dòng),也可以指定只觀察某一類變動(dòng)。 observe方法用來啟動(dòng)監(jiān)聽,它接受兩個(gè)參數(shù)。 第一個(gè)參數(shù):所要觀察的 DOM 節(jié)點(diǎn) 第二個(gè)參數(shù):一個(gè)配置對象,指定所要觀察的特定變動(dòng)
總結(jié):
microtask 和 task 一樣嚴(yán)格按照時(shí)間先后順序執(zhí)行。
microtask 類型的任務(wù)包括 Promise callback和 Mutation callback。
當(dāng) JS 執(zhí)行棧為空時(shí),便生成一個(gè) microtask 檢查點(diǎn)。
最后 概括一些分類
macrotask: script (整體代碼),setTimeout, setInterval, setImmediate, I/O, UI rendering.? microtask: process.nextTick, Promise(原生),Object.observe,MutationObserver 在microtask中 process.nextTick 優(yōu)先級高于 Promise。?
對于任務(wù)名稱的事件隊(duì)列關(guān)系
task queue == macrotask queue != microtask queue
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96972.html
摘要:異步任務(wù)必須指定回調(diào)函數(shù),當(dāng)異步任務(wù)從任務(wù)隊(duì)列回到執(zhí)行棧,回調(diào)函數(shù)就會(huì)執(zhí)行。事件循環(huán)主線程從任務(wù)隊(duì)列中讀取事件,這個(gè)過程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為。事件循環(huán)事件循環(huán)是指主線程重復(fù)從消息隊(duì)列中取消息執(zhí)行的過程。 參考鏈接:這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制https://zhuanlan.zhihu.com/p/...從瀏覽器多進(jìn)程到JS單線程,JS運(yùn)行機(jī)制...
摘要:如果對語法分析和預(yù)編譯,還有疑問引擎執(zhí)行的過程的理解語法分析和預(yù)編譯階段。參與執(zhí)行過程的線程分別是引擎線程也稱為內(nèi)核,負(fù)責(zé)解析執(zhí)行腳本程序的主線程例如引擎。以上便是引擎執(zhí)行宏任務(wù)的整個(gè)過程。 一、概述 js引擎執(zhí)行過程主要分為三個(gè)階段,分別是語法分析,預(yù)編譯和執(zhí)行階段,上篇文章我們介紹了語法分析和預(yù)編譯階段,那么我們先做個(gè)簡單概括,如下: 1、語法分析: 分別對加載完成的代碼塊進(jìn)行語法...
摘要:如果對語法分析和預(yù)編譯,還有疑問引擎執(zhí)行的過程的理解語法分析和預(yù)編譯階段。參與執(zhí)行過程的線程分別是引擎線程也稱為內(nèi)核,負(fù)責(zé)解析執(zhí)行腳本程序的主線程例如引擎。以上便是引擎執(zhí)行宏任務(wù)的整個(gè)過程。一、概述 js引擎執(zhí)行過程主要分為三個(gè)階段,分別是語法分析,預(yù)編譯和執(zhí)行階段,上篇文章我們介紹了語法分析和預(yù)編譯階段,那么我們先做個(gè)簡單概括,如下: 1、語法分析: 分別對加載完成的代碼塊進(jìn)行語法檢驗(yàn),語...
摘要:規(guī)范中定義了瀏覽器何時(shí)進(jìn)行渲染更新,了解它有助于性能優(yōu)化。結(jié)合一些資料,對上邊規(guī)范給出一些理解有誤請指正每個(gè)線程都有自己的。列為,列為,列為。我們都知道是單線程,渲染計(jì)算和腳本運(yùn)行共用同一線程網(wǎng)絡(luò)請求會(huì)有其他線程,導(dǎo)致腳本運(yùn)行會(huì)阻塞渲染。 本文轉(zhuǎn)自blog 轉(zhuǎn)載請注明出處 異步的思考 event loops隱藏得比較深,很多人對它很陌生。但提起異步,相信每個(gè)人都知道。異步背后的靠山就是...
閱讀 556·2021-10-19 11:45
閱讀 1372·2021-09-30 09:48
閱讀 1481·2021-08-16 10:56
閱讀 744·2021-07-26 23:38
閱讀 3216·2019-08-30 13:15
閱讀 2602·2019-08-30 12:45
閱讀 1838·2019-08-29 12:14
閱讀 2087·2019-08-26 18:42