成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

簡(jiǎn)單理解 JavaScript Event Loop

cjie / 1283人閱讀

摘要:由此可以認(rèn)為,實(shí)際上是一系列的回調(diào)函數(shù)集合。此時(shí)瀏覽器會(huì)在其它線程中執(zhí)行異步操作,操作完成后將回調(diào)函數(shù)放入主線程任務(wù)隊(duì)列中。當(dāng)主線程將執(zhí)行棧中的函數(shù)執(zhí)行完畢后,再次讀取任務(wù)隊(duì)列,形成循環(huán)。

先看一段代碼,也是一道經(jīng)典面試題:

(function test() {
    setTimeout(function() {console.log(4)}, 0);
    new Promise(function executor(resolve) {
        console.log(1);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(2);
    }).then(function() {
        console.log(5);
    });
    console.log(3);
})()

其輸出結(jié)果為:

// 1
// 2
// 3
// 5
// 4


我們知道,JavaScript 在同一時(shí)間片內(nèi)只能執(zhí)行一個(gè)任務(wù):

主線程會(huì)依次執(zhí)行代碼,當(dāng)執(zhí)行到函數(shù)的時(shí)候會(huì)將函數(shù)加入執(zhí)行棧,當(dāng)函數(shù)執(zhí)行完畢后再將其出棧,直至代碼執(zhí)行完畢。當(dāng)執(zhí)行棧為空時(shí),runtime 會(huì)從任務(wù)隊(duì)列(先入先出)中取出待執(zhí)行的回調(diào)函數(shù)并執(zhí)行,入棧、出棧的過(guò)程同上。這個(gè)機(jī)制就叫做 Event Loop。

由此可以認(rèn)為,Event Loop實(shí)際上是一系列的回調(diào)函數(shù)集合。

舉例來(lái)說(shuō):在瀏覽器中,對(duì)于網(wǎng)絡(luò)請(qǐng)求等需要等待一段時(shí)間才會(huì)返回結(jié)果的操作,我們通常采用異步回調(diào)來(lái)處理,這個(gè)回調(diào)就會(huì)放入任務(wù)隊(duì)列中。此時(shí)瀏覽器會(huì)在其它線程中執(zhí)行異步操作,操作完成后將回調(diào)函數(shù)放入主線程任務(wù)隊(duì)列中。Event Loop負(fù)責(zé)在主線程執(zhí)行完畢后將任務(wù)隊(duì)列中的函數(shù)放入執(zhí)行棧中,由主線程執(zhí)行。當(dāng)主線程將執(zhí)行棧中的函數(shù)執(zhí)行完畢后,再次讀取任務(wù)隊(duì)列,形成循環(huán)。所以即使主線程阻塞了,任務(wù)隊(duì)列依然能夠被添加函數(shù),因?yàn)槿蝿?wù)隊(duì)列的添加是由瀏覽器負(fù)責(zé)的。(不同的 runtime 實(shí)現(xiàn)可能不同)

另外需要注意的是 Promise.then 是異步執(zhí)行的,而創(chuàng)建 Promise 實(shí)例是同步執(zhí)行的。這就解釋了為什么1、2、3輸出在4、5之前。

但為什么5 會(huì)輸出在4前面呢?

JavaScript 中的任務(wù)又分為MacroTask 與 MicroTask 兩種。

典型的 MacroTask 包含了 :

setTimeout

setInterval

setImmediate

requestAnimationFrame

I/O

UI rendering

而常見(jiàn)的MicroTask 包含了

process.nextTick

Promises

Object.observe

MutationObserver

Event Loop 中有一個(gè)或多個(gè)Task Queue,即MacroTask Queue,僅有一個(gè)Job Queue,即MicroTask Queue。Task Queue的執(zhí)行是按照回調(diào)順序先入先出,而在 MacroTask 的執(zhí)行間隙中會(huì)清空已有的 MicroTask Queue

回到代碼中,setTimeout(function() {console.log(4)}, 0); 既然延遲設(shè)置為0,為什么5會(huì)在4之前輸入呢?

那是因?yàn)閟etTimeout設(shè)置為0的時(shí)候,runtime其實(shí)并不是0,在主流瀏覽器中會(huì)將其設(shè)置為4,而 node 則會(huì)將其設(shè)置為1。那么現(xiàn)在代碼的執(zhí)行順序就很清晰了:

console.log(1);    // 創(chuàng)建 Promise 主線程執(zhí)行
...
console.log(2); // 創(chuàng)建 Promise 主線程執(zhí)行

console.log(3); // test 函數(shù)立即執(zhí)行, 主線程執(zhí)行
... 
console.log(5); // 主線程執(zhí)行完畢,執(zhí)行MicroTask Queue,即 promise.then
... 
console.log(4);    // 執(zhí)行 setTimeout(4)



參考資料:

https://developer.mozilla.org...

https://html.spec.whatwg.org/...

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/94529.html

相關(guān)文章

  • 初窺JavaScript事件機(jī)制的實(shí)現(xiàn)(一)—— Node.js事件驅(qū)動(dòng)實(shí)現(xiàn)概覽

    摘要:如果當(dāng)前沒(méi)有事件也沒(méi)有定時(shí)器事件,則返回。相關(guān)資料關(guān)于的架構(gòu)及設(shè)計(jì)思路的事件討論了使用線程池異步運(yùn)行代碼。下一篇初窺事件機(jī)制的實(shí)現(xiàn)二中定時(shí)器的實(shí)現(xiàn) 在瀏覽器中,事件作為一個(gè)極為重要的機(jī)制,給予JavaScript響應(yīng)用戶(hù)操作與DOM變化的能力;在Node.js中,事件驅(qū)動(dòng)模型則是其高并發(fā)能力的基礎(chǔ)。 學(xué)習(xí)JavaScript也需要了解它的運(yùn)行平臺(tái),為了更好的理解JavaScript的事...

    lavor 評(píng)論0 收藏0
  • event loop 與 vue

    摘要:但是導(dǎo)致了很明顯的性能問(wèn)題。上述兩個(gè)例子其實(shí)是在這個(gè)中找到的,第一個(gè)使用的版本是,這個(gè)版本的實(shí)現(xiàn)是采用了,而后因?yàn)榈睦锏挠?,于是尤雨溪更改了?shí)現(xiàn),換成了,也就是后一個(gè)所使用的。后來(lái)尤雨溪了解到是將回調(diào)放入的隊(duì)列。 結(jié)論 對(duì)于event loop 可以抽象成一段簡(jiǎn)單的代碼表示 for (macroTask of macroTaskQueue) { // 1. Handle cur...

    springDevBird 評(píng)論0 收藏0
  • event loop 與 vue

    摘要:但是導(dǎo)致了很明顯的性能問(wèn)題。上述兩個(gè)例子其實(shí)是在這個(gè)中找到的,第一個(gè)使用的版本是,這個(gè)版本的實(shí)現(xiàn)是采用了,而后因?yàn)榈睦锏挠?,于是尤雨溪更改了?shí)現(xiàn),換成了,也就是后一個(gè)所使用的。后來(lái)尤雨溪了解到是將回調(diào)放入的隊(duì)列。 結(jié)論 對(duì)于event loop 可以抽象成一段簡(jiǎn)單的代碼表示 for (macroTask of macroTaskQueue) { // 1. Handle cur...

    Barry_Ng 評(píng)論0 收藏0
  • Event Loop - JS執(zhí)行機(jī)制

    摘要:心塞塞根據(jù)規(guī)范,事件循環(huán)是通過(guò)任務(wù)隊(duì)列的機(jī)制來(lái)進(jìn)行協(xié)調(diào)的。等便是任務(wù)源,而進(jìn)入任務(wù)隊(duì)列的是他們指定的具體執(zhí)行任務(wù)回調(diào)函數(shù)。然后當(dāng)前本輪的結(jié)束,主線程可以繼續(xù)取下一個(gè)執(zhí)行。 依然是:經(jīng)濟(jì)基礎(chǔ)決定上層建筑。 說(shuō)明 首先,旨在搞清常用的同步異步執(zhí)行機(jī)制 其次,暫時(shí)不討論node.js的Event Loop執(zhí)行機(jī)制,以下關(guān)于瀏覽器的Event Loop執(zhí)行機(jī)制 最后,借鑒了很多前輩的研究文...

    muddyway 評(píng)論0 收藏0
  • 理解JS中的Event Loop機(jī)制

    摘要:前言前幾天在理解的事件環(huán)機(jī)制中引發(fā)了我對(duì)瀏覽器里的好奇。接下來(lái)理解瀏覽器中的,先看一張圖堆和棧堆是用戶(hù)主動(dòng)請(qǐng)求而劃分出來(lái)的內(nèi)存區(qū)域,比如你,就是將一個(gè)對(duì)象存入堆中,可以理解為存對(duì)象。廢話不多說(shuō),直接上圖個(gè)人理解。參考資料運(yùn)行機(jī)制詳解再談 前言 前幾天在理解node的事件環(huán)機(jī)制中引發(fā)了我對(duì)瀏覽器里Event Loop的好奇。我們都知道javascript是單線程的,任務(wù)是需要一個(gè)一個(gè)按順...

    MASAILA 評(píng)論0 收藏0
  • JavaScript執(zhí)行機(jī)制、事件循環(huán)

    摘要:曾經(jīng)的理解首先,是單線程語(yǔ)言,也就意味著同一個(gè)時(shí)間只能做一件事,那么為什么不是多線程呢這樣還能提高效率啊假定同時(shí)有兩個(gè)線程,一個(gè)線程在某個(gè)節(jié)點(diǎn)上編輯了內(nèi)容,而另一個(gè)線程刪除了這個(gè)節(jié)點(diǎn),這時(shí)瀏覽器就很懵逼了,到底以執(zhí)行哪個(gè)操作呢所以,設(shè)計(jì)者把 Event Loop曾經(jīng)的理解 首先,JS是單線程語(yǔ)言,也就意味著同一個(gè)時(shí)間只能做一件事,那么 為什么JavaScript不是多線程呢?這樣還能提...

    rose 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<