乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       Coder編程 2021-08-23

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

      JS主要的特點就是單線程,所謂單線程就是進程中只有一個線程在運行。

      為什么JS是單線程的而不是多線程的呢?

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

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

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

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

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

      JS引擎執(zhí)行異步代碼不用等待,是因為有事件隊列和事件循環(huán)。

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

      事件隊列是一個存儲著待執(zhí)行任務(wù)的序列,其中的任務(wù)嚴格按照時間先后順序執(zhí)行,排在隊頭的任務(wù)會率先執(zhí)行,而排在隊尾的任務(wù)會最后執(zhí)行。(即先進先出)

      事件隊列:

      • 一個線程中,事件循環(huán)是唯一的,但是任務(wù)隊列可以有多個;
      • 任務(wù)隊列又分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等稱為任務(wù)源,而進入任務(wù)隊列的是他們制定的具體執(zhí)行任務(wù);來自不同任務(wù)源的任務(wù)會進入到不同的任務(wù)隊列,其中setTimeout與setInterval是同源的。
       

      事件循環(huán)運行機制

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

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

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

      (4)當前微任務(wù)執(zhí)行完畢,開始檢查渲染,然后GUI線程接管渲染;

      (5)渲染完畢后,JS線程繼續(xù)接管,開始下一個宏任務(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)機制分析以上代碼運行流程:

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

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

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

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

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

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

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

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多