小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

事件循環(huán) EventLoop(Promise,setTimeOut,async/await執(zhí)行順序)

 Coder編程 2021-08-23

什么是事件循環(huán)?想要了解什么是事件循環(huán)就要從js的工作原理開(kāi)始說(shuō)起:

JS主要的特點(diǎn)就是單線(xiàn)程,所謂單線(xiàn)程就是進(jìn)程中只有一個(gè)線(xiàn)程在運(yùn)行。

為什么JS是單線(xiàn)程的而不是多線(xiàn)程的呢?

JS的主要用途就是與用戶(hù)交互,操作DOM,假設(shè)JS同時(shí)有兩個(gè)線(xiàn)程,一個(gè)線(xiàn)程中在某個(gè)DOM節(jié)點(diǎn)上添加或者修改內(nèi)容,而另一個(gè)線(xiàn)程在這個(gè)DOM節(jié)點(diǎn)上執(zhí)行刪除該節(jié)點(diǎn)操作,這樣就會(huì)產(chǎn)生沖突。

單線(xiàn)程就意味著所有任務(wù)都需要排隊(duì),前一任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù),當(dāng)是如果當(dāng)遇到前一個(gè)任務(wù)耗時(shí)很長(zhǎng)的情況,后一個(gè)任務(wù)就不得不一直等著。因此,就有了同步任務(wù)、異步任務(wù)。

同步任務(wù)和異步任務(wù)在js中是如何執(zhí)行的呢?

js的代碼運(yùn)行會(huì)形成一個(gè)主線(xiàn)程和一個(gè)任務(wù)隊(duì)列。主線(xiàn)程會(huì)自上而下依次執(zhí)行我們的js代碼,形成一個(gè)執(zhí)行棧。

同步任務(wù)就會(huì)被放到這個(gè)主線(xiàn)程中依次執(zhí)行。而異步任務(wù)被放入到任務(wù)隊(duì)列中執(zhí)行,執(zhí)行完就會(huì)在任務(wù)隊(duì)列中打一個(gè)標(biāo)記,形成一個(gè)對(duì)應(yīng)的事件。當(dāng)主線(xiàn)程中的任務(wù)全部運(yùn)行完畢,js會(huì)去提取并執(zhí)行任務(wù)隊(duì)列中的事件。這個(gè)過(guò)程是循環(huán)進(jìn)行的,這就是EventLoop。

JS引擎執(zhí)行異步代碼不用等待,是因?yàn)橛惺录?duì)列和事件循環(huán)。

事件循環(huán)是指主線(xiàn)程重復(fù)從事件隊(duì)列中取消息、執(zhí)行的過(guò)程。指整個(gè)執(zhí)行流程。

事件隊(duì)列是一個(gè)存儲(chǔ)著待執(zhí)行任務(wù)的序列,其中的任務(wù)嚴(yán)格按照時(shí)間先后順序執(zhí)行,排在隊(duì)頭的任務(wù)會(huì)率先執(zhí)行,而排在隊(duì)尾的任務(wù)會(huì)最后執(zhí)行。(即先進(jìn)先出)

事件隊(duì)列:

  • 一個(gè)線(xiàn)程中,事件循環(huán)是唯一的,但是任務(wù)隊(duì)列可以有多個(gè);
  • 任務(wù)隊(duì)列又分macro-task(宏任務(wù))和micro-task(微任務(wù));
  • macro-task包括:script(整體代碼)、setTimeout、setInterval、setImmediate、I/O、UI rendering;
  • micro-task包括:process.nextTick, Promise, Object.observe(已廢棄), MutationObserver(html5新特性)
  • setTimeout/Promise等稱(chēng)為任務(wù)源,而進(jìn)入任務(wù)隊(duì)列的是他們制定的具體執(zhí)行任務(wù);來(lái)自不同任務(wù)源的任務(wù)會(huì)進(jìn)入到不同的任務(wù)隊(duì)列,其中setTimeout與setInterval是同源的。
 

事件循環(huán)運(yùn)行機(jī)制

(1)執(zhí)行一個(gè)宏任務(wù)(棧中沒(méi)有就從事件隊(duì)列中獲?。?/p>

(2)執(zhí)行過(guò)程中如果遇到微任務(wù),就將它添加到微任務(wù)的任務(wù)隊(duì)列中;

(3)宏任務(wù)執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列的所有微任務(wù);

(4)當(dāng)前微任務(wù)執(zhí)行完畢,開(kāi)始檢查渲染,然后GUI線(xiàn)程接管渲染;

(5)渲染完畢后,JS線(xiàn)程繼續(xù)接管,開(kāi)始下一個(gè)宏任務(wù)。

 

 

事例:

                 async function async1() {           
                     console.log("async1 start");  //(2)        
                     await  async2();            
                     console.log("async1 end");   //(6)    
                 }        
                 async  function async2() {          
                     console.log( 'async2');   //(3)     
                 }       
                 console.log("script start");  //(1)      
                 setTimeout(function () {            
                     console.log("settimeout");  //(8)      
                 },0);        
                 async1();        
                 new Promise(function (resolve) {           
                     console.log("promise1");   //(4)         
                     resolve();        
                 }).then(function () {            
                     console.log("promise2");    //(7)    
                 });        
                 console.log('script end');//(5)

 

按照事件循環(huán)機(jī)制分析以上代碼運(yùn)行流程:

  1. 首先,事件循環(huán)從宏任務(wù)(macrotask)隊(duì)列開(kāi)始,首先讀取script(整體代碼)任務(wù);當(dāng)遇到任務(wù)源(task source)時(shí),則會(huì)先分發(fā)任務(wù)到對(duì)應(yīng)的任務(wù)隊(duì)列中去。

  2. 然后我們看到首先定義了兩個(gè)async函數(shù),此時(shí)沒(méi)有調(diào)用,接著往下看,然后遇到了 `console` 語(yǔ)句,直接輸出 `script start`。輸出之后,script 任務(wù)繼續(xù)往下執(zhí)行,遇到 `setTimeout`,其作為一個(gè)宏任務(wù)源,則會(huì)先將其任務(wù)分發(fā)到對(duì)應(yīng)的任務(wù)隊(duì)列中。

  3. script 任務(wù)繼續(xù)往下執(zhí)行,執(zhí)行了async1()函數(shù),async函數(shù)中在await之前的代碼是立即執(zhí)行的,所以會(huì)立即輸出`async1 start`。
遇到了await時(shí),會(huì)將await后面的表達(dá)式執(zhí)行一遍,所以就緊接著輸出`async2`,然后將await后面的代碼也就是`console.log('async1 end')`加入到microtask中的Promise隊(duì)列中,接著跳出async1函數(shù)來(lái)執(zhí)行后面的代碼。

  4. script任務(wù)繼續(xù)往下執(zhí)行,遇到Promise實(shí)例。由于Promise中的函數(shù)是立即執(zhí)行的,而后續(xù)的 `.then` 則會(huì)被分發(fā)到 microtask 的 `Promise` 隊(duì)列中去。所以會(huì)先輸出 `promise1`,然后執(zhí)行 `resolve`,將 `promise2` 分配到對(duì)應(yīng)隊(duì)列。

  5. script任務(wù)繼續(xù)往下執(zhí)行,輸出了 `script end`,至此,全局任務(wù)就執(zhí)行完畢了。
根據(jù)上述,每次執(zhí)行完一個(gè)宏任務(wù)之后,會(huì)去檢查是否存在 Microtasks;如果有,則執(zhí)行 Microtasks 直至清空 Microtask Queue。
因而在script任務(wù)執(zhí)行完畢之后,開(kāi)始查找清空微任務(wù)隊(duì)列。此時(shí),微任務(wù)中, `Promise` 隊(duì)列有的兩個(gè)任務(wù)`async1 end`和`promise2`,因此按事件隊(duì)列先進(jìn)先出的原則,先后順序輸出 `async1 end,promise2`。當(dāng)所有的 Microtasks 執(zhí)行完畢之后,表示第一輪的循環(huán)就結(jié)束了。

  6. 第二輪循環(huán)依舊從宏任務(wù)隊(duì)列開(kāi)始。此時(shí)宏任務(wù)中只有一個(gè) `setTimeout`,取出直接輸出即可,至此整個(gè)流程結(jié)束。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多