亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

js事件循環(huán)機(jī)制(瀏覽器端Event Loop) 以及async/await的理解

CKJOKER / 1804人閱讀

摘要:接下來處理微任務(wù)隊列,打印,后面一個不會有任何打印,但是會執(zhí)行執(zhí)行后面的代碼打印進(jìn)入第二次事件循環(huán),執(zhí)行宏任務(wù)隊列打印

事件循環(huán)機(jī)制

理解js的事件循環(huán)機(jī)制,能夠很大程度的幫我們更深層次的理解平時遇到的一些很疑惑的問題

簡單版本

下面來看一段代碼,想想它的結(jié)果和你的結(jié)果是否一樣

    setTimeout(function() {
        console.log(1)
    }, 0)
    
    console.log(2)
    
    //  執(zhí)行結(jié)果是 2 1

我們可以將js的任務(wù)分為同步任務(wù)異步任務(wù), 按照這種分類js的執(zhí)行機(jī)制如下

任務(wù)執(zhí)行隊列分為同步任務(wù)隊列異步任務(wù)隊列

代碼執(zhí)行時,遇到同步代碼,會被直接推入同步任務(wù)隊列并依次執(zhí)行

遇到異步代碼(如setTimeout、setInterval), 會被直接推入異步任務(wù)隊列

當(dāng)同步任務(wù)隊列執(zhí)行完畢,這個時候異步任務(wù)隊列的任務(wù)會被依次推入同步任務(wù)隊列并依次執(zhí)行

所以上面的代碼執(zhí)行的時候, setTimeout()不會被立即執(zhí)行,會被推到異步任務(wù)隊列里面, 之后再執(zhí)行console.log(2), 同步任務(wù)隊列任務(wù)執(zhí)行完畢之后,會去異步任務(wù)隊列的任務(wù)會被依次推到 同步任務(wù)隊列并執(zhí)行

終極版本

下面來看一段代碼,想想它的結(jié)果和你的結(jié)果是否一樣

    setTimeout(function() {
        console.log(1)
    }, 0)
    
    new Promise(function(resolve, reject) {
        console.log(2)
        resolve()
    }).then((res) => {
        console.log(3)
    })
    console.log(4)
    
    // 執(zhí)行結(jié)果是 2 4 3 1

js異步任務(wù)按照準(zhǔn)確的劃分,應(yīng)該將任務(wù)分為

宏任務(wù): setTimeout、setInterval

微任務(wù): 例如Promise.then方法。注意new Promsie()的時候是同步,立即執(zhí)行。

注意: 現(xiàn)在有三個隊列: 同步隊列(也稱執(zhí)行棧)、宏任務(wù)隊列、微任務(wù)隊列

所以針對這種機(jī)制,js的事件循環(huán)機(jī)制應(yīng)該是這樣的

遇到同步代碼,依次推入同步隊列并執(zhí)行

當(dāng)遇到setTimeout、setInterval,會被推到宏任務(wù)隊列

如果遇到.then,會被當(dāng)作微任務(wù),被推入微任務(wù)隊列

同步隊列執(zhí)行完畢,然后會去微隊列取任務(wù),直到微隊列清空。然后檢查宏隊列,去宏隊列取任務(wù),并且每一個宏任務(wù)執(zhí)行完畢都會去微隊列跑一遍,看看有沒有新的微任務(wù),有的話再把微任務(wù)清空。這樣依次循環(huán)

 console.log(1);
    
 setTimeout(() => {
   console.log("setTimeout");
 }, 0);

 let promise = new Promise(resolve => {
   console.log(3);
   resolve();
 }).then(data => {
   console.log(100);
 }).then(data => {
   console.log(200);
 });
    
 console.log(2);

所以對于以上的代碼執(zhí)行流程如下:

遇到同步任務(wù)先輸出1。

setTimeout是宏任務(wù),會先放到宏任務(wù)隊列中。

new Promise是立即執(zhí)行的,所以會先輸出3。

Promise.then是微任務(wù),會依次排列到微任務(wù)隊列中,繼續(xù)向下執(zhí)行輸出2。

現(xiàn)在執(zhí)行棧中的任務(wù)已經(jīng)清空,再將微任務(wù)隊列清空,依次輸出100和200。

然后每次取出一個宏任務(wù),因為現(xiàn)在只有一個宏任務(wù),所以最后輸出setTimeout。

async/await async

當(dāng)我們在函數(shù)前使用async的時候,使得該函數(shù)返回的是一個Promise對象

async function test() {
    return 1   // async的函數(shù)會在這里幫我們隱士使用Promise.resolve(1)
}
// 等價于下面的代碼
function test() {
   return new Promise(function(resolve, reject) {
       resolve(1)
   })
}

可見async只是一個語法糖,只是幫助我們返回一個Promise而已

await

await表示等待,是右側(cè)「表達(dá)式」的結(jié)果,這個表達(dá)式的計算結(jié)果可以是 Promise 對象的值或者一個函數(shù)的值(換句話說,就是沒有特殊限定)。并且只能在帶有async的內(nèi)部使用

使用await時,會從右往左執(zhí)行,當(dāng)遇到await時,會阻塞函數(shù)內(nèi)部處于它后面的代碼,去執(zhí)行該函數(shù)外部的同步代碼,當(dāng)外部同步代碼執(zhí)行完畢,再回到該函數(shù)內(nèi)部執(zhí)行剩余的代碼, 并且當(dāng)await執(zhí)行完畢之后,會先處理微任務(wù)隊列的代碼

下面來看一個栗子:

        async function async1() {
            console.log( "async1 start" )
            await async2()
            console.log( "async1 end" )
        }
        async function async2() {
            console.log( "async2" )
        }
        console.log( "script start" )
        setTimeout( function () {
            console.log( "setTimeout" )
        }, 0 )
        async1();
        new Promise( function ( resolve ) {
            console.log( "promise1" )
            resolve();
        } ).then( function () {
            console.log( "promise2" )
        } )
        console.log( "script end" )
        
       

下面是在chrome瀏覽器上輸出的結(jié)果

使用事件循環(huán)機(jī)制分析:

首先執(zhí)行同步代碼,console.log( "script start" )

遇到setTimeout,會被推入宏任務(wù)隊列

執(zhí)行async1(), 它也是同步的,只是返回值是Promise,在內(nèi)部首先執(zhí)行console.log( "async1 start" )

然后執(zhí)行async2(), 然后會打印console.log( "async2" )

從右到左會執(zhí)行, 當(dāng)遇到await的時候,阻塞后面的代碼,去外部執(zhí)行同步代碼

進(jìn)入 new Promise,打印console.log( "promise1" )

.then放入事件循環(huán)的微任務(wù)隊列

繼續(xù)執(zhí)行,打印console.log( "script end" )

外部同步代碼執(zhí)行完畢,接著回到async1()內(nèi)部, 由于async2()其實是返回一個Promise, await async2()相當(dāng)于獲取它的值,其實就相當(dāng)于這段代碼Promise.resolve(undefined).then((undefined) => {}),所以.then會被推入微任務(wù)隊列, 所以現(xiàn)在微任務(wù)隊列會有兩個任務(wù)。接下來處理微任務(wù)隊列,打印console.log( "promise2" ),后面一個.then不會有任何打印,但是會執(zhí)行

執(zhí)行后面的代碼, 打印console.log( "async1 end" )

進(jìn)入第二次事件循環(huán),執(zhí)行宏任務(wù)隊列, 打印console.log( "setTimeout" )

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/100510.html

相關(guān)文章

  • 最后一次搞懂 Event Loop

    摘要:由于是單線程的,這些方法就會按順序被排列在一個單獨的地方,這個地方就是所謂執(zhí)行棧。事件隊列每次僅執(zhí)行一個任務(wù),在該任務(wù)執(zhí)行完畢之后,再執(zhí)行下一個任務(wù)。 Event Loop 是 JavaScript 異步編程的核心思想,也是前端進(jìn)階必須跨越的一關(guān)。同時,它又是面試的必考點,特別是在 Promise 出現(xiàn)之后,各種各樣的面試題層出不窮,花樣百出。這篇文章從現(xiàn)實生活中的例子入手,讓你徹底理解 E...

    gself 評論0 收藏0
  • 筆試題之Event Loop終極篇

    摘要:下面開始分析開頭的代碼第一輪事件循環(huán)流程整體作為第一個宏任務(wù)進(jìn)入主線程,遇到,輸出遇到函數(shù)聲明,聲明暫時不用管遇到,其回調(diào)函數(shù)被分發(fā)到微任務(wù)中。我們記為遇到,其回調(diào)函數(shù)被分發(fā)到宏任務(wù)中。 先上一道常見的筆試題 console.log(1); async function async1() { console.log(2); await async2(); con...

    niceforbear 評論0 收藏0
  • 由setTimeout深入JavaScript執(zhí)行環(huán)境異步機(jī)制

    摘要:圖片轉(zhuǎn)引自的演講和兩個定時器中回調(diào)的執(zhí)行邏輯便是典型的機(jī)制。異步編程關(guān)于異步編程我的理解是,在執(zhí)行環(huán)境所提供的異步機(jī)制之上,在應(yīng)用編碼層面上實現(xiàn)整體流程控制的異步風(fēng)格。 問題背景 在一次開發(fā)任務(wù)中,需要實現(xiàn)如下一個餅狀圖動畫,基于canvas進(jìn)行繪圖,但由于對于JS運行環(huán)境中異步機(jī)制的不了解,所以遇到了一個棘手的問題,始終無法解決,之后在與同事交流之后才恍然大悟。問題的根節(jié)在于經(jīng)典的J...

    codeGoogle 評論0 收藏0
  • 面試題之Event Loop終極篇

    摘要:下面開始分析開頭的代碼第一輪事件循環(huán)流程整體作為第一個宏任務(wù)進(jìn)入主線程,遇到,輸出遇到函數(shù)聲明,聲明暫時不用管遇到,其回調(diào)函數(shù)被分發(fā)到微任務(wù)中。我們記為遇到,其回調(diào)函數(shù)被分發(fā)到宏任務(wù)中。 先上一道常見的筆試題 console.log(1); async function async1() { console.log(2); await async2(); con...

    233jl 評論0 收藏0
  • 理清覽器事件循環(huán)機(jī)制Event Loop

    摘要:何為事件循環(huán)機(jī)制的任務(wù)分兩種,分別是同步任務(wù)和異步任務(wù)。如上圖所示主線程在執(zhí)行代碼的時候,遇到異步任務(wù)進(jìn)入并注冊回調(diào)函數(shù),有了運行結(jié)果后將它添加到事件隊列中,然后繼續(xù)執(zhí)行下面的代碼,直到同步代碼執(zhí)行完。 我們知道,JavaScript作為瀏覽器的腳本語言,起初是為了與用戶交互和操作DOM,為了避免因為同時操作了同一DOM節(jié)點而引起沖突,被設(shè)計成為一種單線程語言。而單線程語言最大的特性就...

    nemo 評論0 收藏0

發(fā)表評論

0條評論

CKJOKER

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<