欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Javascript運行機(jī)制之Event Loop

 更新時間:2021年12月30日 11:54:27   作者:耀_  
這篇文章主要介紹了Javascript運行機(jī)制之Event Loop,在學(xué)習(xí)Event Loop前,首先需要了解的幾個概念Javascript是單線程、任務(wù)隊列、同步任務(wù)、異步任務(wù)、Javascript執(zhí)行棧,下面來看看文章的詳細(xì)介紹吧

一、四個概念

1、Javascript是單線程

單線程意味著我們的js代碼只能從上往下同步執(zhí)行,同一時間只能執(zhí)行一個任務(wù),這會導(dǎo)致某些執(zhí)行時間較長或者執(zhí)行時間不確定的任務(wù)會卡住其它任務(wù)的正常執(zhí)行,Event Loop出現(xiàn)的原因正是為了解決此問題。

2、任務(wù)隊列

為了解決上述的排隊問題,有了任務(wù)隊列,瀏覽器在異步任務(wù)有了結(jié)果后,將其添加到任務(wù)隊列,以待將來執(zhí)行,其他任務(wù)就在主線程上同步執(zhí)行。

這里要注意的是,向任務(wù)隊列中添加任務(wù)的時機(jī)是異步任務(wù)有結(jié)果后。其實任務(wù)隊列中存在的就是異步任務(wù)的回調(diào)函數(shù)。

3、同步任務(wù)、異步任務(wù)

Js程序中的同步任務(wù)是指在主線程中執(zhí)行的任務(wù),異步任務(wù)是指進(jìn)入任務(wù)隊列中的任務(wù)

4、Javascript執(zhí)行棧

所有的同步任務(wù)都在主線程上執(zhí)行,行成一個執(zhí)行棧。當(dāng)主線程上任務(wù)執(zhí)行完畢后,從任務(wù)隊列中取出任務(wù)執(zhí)行。

var name = "zhouwei";

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

console.log(name);


上面代碼在瀏覽器中執(zhí)行如下,我們將程序全局執(zhí)行環(huán)境的代碼理解為包裹在一個main函數(shù)中的代碼,這段代碼的執(zhí)行棧變化如下圖:

  • 開始執(zhí)行代碼,將main任務(wù)(全局代碼入棧執(zhí)行),當(dāng)遇到異步任務(wù)(setTimeout后)。
  • 瀏覽器接管異步任務(wù),并在1s后將異步任務(wù)的結(jié)果(回調(diào)函數(shù))添加到任務(wù)隊列。
  • 執(zhí)行棧中的同步任務(wù)執(zhí)行完畢,此時任務(wù)隊列為空(未到1s),執(zhí)行棧也為空
  • 異步任務(wù)有結(jié)果后,首先進(jìn)入任務(wù)隊列排隊(因為可能有很多異步任務(wù))。
  • 執(zhí)行棧從任務(wù)隊列中取出任務(wù)開始同步執(zhí)行。
  • 重復(fù)執(zhí)行第5步。

二、Event Loop

Js執(zhí)行棧不斷的從任務(wù)隊列中讀取任務(wù)并執(zhí)行的過程就是Event Loop

我們知道任務(wù)隊列中存放的是異步任務(wù)的結(jié)果,那么異步任務(wù)都有哪些了?

  • 1、事件

Javascript中的事件有很多,都是屬于異步任務(wù)。由瀏覽器接管,當(dāng)事件觸發(fā)時,將事件的回調(diào)加入的任務(wù)隊列中,在Js執(zhí)行棧中沒有任務(wù)時執(zhí)行。

  • 2、Http請求
  • 3、定時器
  • 4、requestAnimationFrame等

宏任務(wù)(macrotask)和微任務(wù)(microtask)
在了解了任務(wù)隊列和Event Loop后,我們知道了Js執(zhí)行棧從任務(wù)隊列中讀取任務(wù)執(zhí)行,但這個具體工程我們?nèi)蝿?wù)不清楚,這里引出了宏任務(wù)和微任務(wù)的的概念,幫助我們理解Event Loop。

進(jìn)入任務(wù)隊列中的異步任務(wù)回調(diào)分為了宏任務(wù)和微任務(wù), Js執(zhí)行棧執(zhí)行宏任務(wù)和微任務(wù)的規(guī)則如下圖所示。

Js執(zhí)行棧首先執(zhí)行一個宏任務(wù)(全局代碼) -> 從任務(wù)隊列中讀取所有微任務(wù)執(zhí)行 -> UI rendering(瀏覽器渲染界面) -> 從任務(wù)隊列讀取一個宏任務(wù) -> 所有微任務(wù) -> UI rendering -> …

在每一輪的Event Loop結(jié)束后(1個宏任務(wù) + 所有微任務(wù)),瀏覽器開始渲染界面(如果有需要渲染的UI,否則不執(zhí)行UI rendering),在UI rendering結(jié)束后,開始下一輪Event Loop。

哪些是宏任務(wù)?

  • setTimeout
  • setInterval
  • setImmediate (Node)
  • requestAnimationFrame (瀏覽器)
  • I/O (事件回調(diào))
  • UI rendering (瀏覽器渲染)

哪些是微任務(wù)?

  • Promise
  • process.nextTick (Node)
  • MutationObserver (現(xiàn)代瀏覽器提供的用來檢測 DOM 變化的網(wǎng)頁接口)

setTimeout延時問題

一般來說在代碼中setTimeout中回調(diào)的執(zhí)行時間都是大于設(shè)置的時間。 這是因為在setTimeout指定時間到達(dá)后,雖然回調(diào)函數(shù)被添加到了任務(wù)隊列,但是此時Js執(zhí)行棧中可能有正在執(zhí)行的任務(wù),此回調(diào)需要等待Js執(zhí)行棧的任務(wù)執(zhí)行完畢后才有機(jī)會執(zhí)行,這就是setTimeout延時問題。

三、實戰(zhàn)

練習(xí)下下方代碼輸出結(jié)果吧:

console.log(1);

setTimeout(() => {
    console.log(2);
    Promise.resolve().then(() => {
        console.log(3)
    });
});

new Promise(resolve => {
    console.log(4);
    setTimeout(() => {
        console.log(5);
    });
    resolve(6)
}).then(data => {
    console.log(data);
})

setTimeout(() => {
    console.log(7);
})

console.log(8);

用上方的我們說過的js執(zhí)行機(jī)制來分析這道題:

1: 執(zhí)行全局任務(wù)中的同步代碼輸出:

1
4
8

這里需要注意的是Promise接受的handle函數(shù)是同步任務(wù),而then方法是異步任務(wù),所以會直接輸出4。

2: 這時的任務(wù)隊列中有三個setTimeout的宏任務(wù),和一個Promise的微任務(wù)

// 此時的宏任務(wù)是

setTimeout(() => {
    console.log(2);
    Promise.resolve().then(() => {
        console.log(3)
    });
});

setTimeout(() => {
    console.log(5);
});


setTimeout(() => {
    console.log(7);
})

// 此時微任務(wù)是
then(data => {
    console.log(data);
})

執(zhí)行一個微任務(wù), 輸出:6

3: 接著執(zhí)行第一個宏任務(wù)

setTimeout(() => {
    console.log(2);
    Promise.resolve().then(() => {
        console.log(3)
    });
});


輸出:2

在此宏任務(wù)中,向任務(wù) 隊列添加了一個微任務(wù)。此時任務(wù)隊列有了新的微任務(wù)。

4:執(zhí)行一個微任務(wù),輸出:3

then(() => {
   console.log(3)
});


5: 繼續(xù)按照規(guī)則執(zhí)行任務(wù), 輸出: 5、7

整體輸出情況是:

1、4、8、6、2、3、5、7

你的答案是不是這樣呢?

總結(jié):

  • javascritp的任務(wù)分為同步任務(wù)和異步任務(wù)
  • 同步任務(wù)在主線程(Js執(zhí)行棧)中執(zhí)行,異步任務(wù)被其他線程接管,并在異步任務(wù)有結(jié)果后,將其回調(diào)添加到任務(wù)隊列。
  • 任務(wù)隊列中的任務(wù)分為了宏任務(wù)和微任務(wù)。Js執(zhí)行??偸窍葓?zhí)行一個宏任務(wù),再執(zhí)行完所有微任務(wù)…

到此這篇關(guān)于Javascript運行機(jī)制之Event Loop的文章就介紹到這了,更多相關(guān)Javascript運行機(jī)制Event Loop內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • js實現(xiàn)QQ面板拖拽效果(慕課網(wǎng)DOM事件探秘)(全)

    js實現(xiàn)QQ面板拖拽效果(慕課網(wǎng)DOM事件探秘)(全)

    這篇文章主要為大家詳細(xì)介紹了QQ面板拖拽效果,探秘慕課網(wǎng)DOM事件,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Textarea與懶惰渲染實現(xiàn)代碼

    Textarea與懶惰渲染實現(xiàn)代碼

    2008年有啊第一次性能優(yōu)化時,我們曾用textarea來存貯需要懶惰渲染的節(jié)點
    2012-01-01
  • JavaScript?TWaver使用中間點畫折線的方法

    JavaScript?TWaver使用中間點畫折線的方法

    這篇文章主要介紹了JavaScript?TWaver使用中間點畫折線的方法,TWaver的圖形組件庫中提供了拓?fù)浣M件、地圖組件、設(shè)備圖組件,以及表格、樹圖、屬性表、圖表等豐富的通用圖形界面組件
    2022-07-07
  • JavaScript變量聲明var,let.const及區(qū)別淺析

    JavaScript變量聲明var,let.const及區(qū)別淺析

    這篇文章主要介紹了JavaScript變量聲明var,let.const及區(qū)別淺析,需要的朋友可以參考下
    2018-04-04
  • JavaScript變量基本使用方法實例分析

    JavaScript變量基本使用方法實例分析

    這篇文章主要介紹了JavaScript變量基本使用方法,結(jié)合實例形式分析了JavaScript變量的類型、使用注意事項及命名規(guī)范,需要的朋友可以參考下
    2019-11-11
  • 微信小程序?qū)崿F(xiàn)授權(quán)登錄

    微信小程序?qū)崿F(xiàn)授權(quán)登錄

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)授權(quán)登錄,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 關(guān)于ES6的六個小特性(二)

    關(guān)于ES6的六個小特性(二)

    ES6提供了大量新的好的東西,在過去的一年內(nèi),瀏覽器提供商做了大量的辛勤工作將新的語言特性更新到他們的瀏覽器中。盡管有重大的更新,很多小的語言更新另我眼前一亮,下面這篇文章主要介紹了關(guān)于ES6的六個小特性,需要的朋友可以參考下。
    2017-02-02
  • js實現(xiàn)文字超出部分用省略號代替實例代碼

    js實現(xiàn)文字超出部分用省略號代替實例代碼

    關(guān)于超出一定字?jǐn)?shù)用省略號顯示的問題,這種要求在我們?nèi)粘i_發(fā)的時候經(jīng)常見到,我們之前基本都是用CSS來完成的,今天給大家分享個Javascript實現(xiàn)這個功能的示例代碼,有需要的可以參考借鑒。
    2016-09-09
  • js日期對象兼容性的處理方法

    js日期對象兼容性的處理方法

    本篇文章主要是對js日期對象兼容性的處理方法進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • 分享19個JavaScript 有用的簡寫寫法

    分享19個JavaScript 有用的簡寫寫法

    最近很火的一篇來自國外的文章,js的簡寫寫法一定程度上可以提高你的js書寫水平對于js的理解也會更近一步
    2017-07-07

最新評論