国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript:并發(fā)模型與Event Loop

DevWiki / 3377人閱讀

摘要:需要注意的是,定時(shí)器只是將事件插入了任務(wù)隊(duì)列,必須等到當(dāng)前代碼執(zhí)行棧執(zhí)行完,主線程才會去執(zhí)行它指定的回調(diào)函數(shù)。如果當(dāng)前代碼耗時(shí)很長,有可能要等很久,所以并沒有辦法保證,回調(diào)函數(shù)一定會在指定的時(shí)間執(zhí)行。這也引申出的并發(fā)模型。

一、JavaScript的單線程

眾所周知,JavaScript的一大特點(diǎn)就是單線程,但是我們有沒有思考過它為什么不能是多線程的?

我們假定JavaScript有兩個(gè)線程,一個(gè)線程在某個(gè)DOM節(jié)點(diǎn)上添加內(nèi)容,另一個(gè)線程刪除了這個(gè)節(jié)點(diǎn),這時(shí)瀏覽器應(yīng)該以哪個(gè)線程為準(zhǔn)?所以為了避免這種復(fù)雜性,從一誕生,JavaScript就是單線程。

盡管HTML5提出Web Worker,允許JavaScript腳本創(chuàng)建多個(gè)線程,但是子線程完全受主線程控制,且不得操作DOM。所以,并沒有改變JavaScript單線程的本質(zhì)。

二、定時(shí)器

定時(shí)器主要是setTimeout()和setInterval()這兩個(gè)函數(shù),這也是平時(shí)編程時(shí)候用到最多的。

console.log(1);
setTimeout(function() {
    console.log(2);
},5000);
console.log(3);

上面代碼的執(zhí)行結(jié)果是1,3,2。但如果將setTimeout()的第二個(gè)參數(shù)設(shè)為0,就表示當(dāng)前代碼執(zhí)行完以后,立即執(zhí)行(0毫秒延遲)指定的回調(diào)函數(shù)。setTimeout(fn,0)的含義是,它在任務(wù)隊(duì)列的尾部添加一個(gè)事件,在主線程最早得到空閑時(shí)去執(zhí)行,也就是說,盡可能早得執(zhí)行。

需要注意的是,定時(shí)器只是將事件插入了任務(wù)隊(duì)列,必須等到當(dāng)前代碼(執(zhí)行棧)執(zhí)行完,主線程才會去執(zhí)行它指定的回調(diào)函數(shù)。如果當(dāng)前代碼耗時(shí)很長,有可能要等很久,所以并沒有辦法保證,回調(diào)函數(shù)一定會在setTimeout()指定的時(shí)間執(zhí)行。這也引申出JavaScript的并發(fā)模型

三、并發(fā)模型

我們先看一下理論上的并發(fā)模型:

棧(stack):函數(shù)調(diào)用會形成了一個(gè)堆棧幀
堆(heap):對象被分配在一個(gè)堆中,一個(gè)用以表示一個(gè)內(nèi)存中大的未被組織的區(qū)域
隊(duì)列(queue):運(yùn)行時(shí)包含的一個(gè)待處理的消息隊(duì)列。當(dāng)棧為空時(shí),則從隊(duì)列中取出一個(gè)消息進(jìn)行處理。這個(gè)處理過程包含了調(diào)用與這個(gè)消息相關(guān)聯(lián)的函數(shù)(以及因而創(chuàng)建了一個(gè)初始堆棧幀)

四、Event Loop

針對上面的并發(fā)模型和JavaScript的同步異步運(yùn)行機(jī)制,我們可以看到整個(gè)流程大致是這樣的:

1.所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧(并發(fā)模型的stack)。
2.主線程之外,還存在一個(gè)任務(wù)隊(duì)列(并發(fā)模型的queue)。只要異步任務(wù)有了運(yùn)行結(jié)果,就在任務(wù)隊(duì)列中放置一個(gè)事件。
3.一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會讀取任務(wù)隊(duì)列,看看里面有哪些事件和那些對應(yīng)的異步任務(wù),于是等待結(jié)束狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。
4.主線程不斷重復(fù)上面的第三步。

這個(gè)過程是循環(huán)不斷的,所以這種運(yùn)行機(jī)制又稱為Event Loop(事件循環(huán))。放一張大神演講時(shí)的圖片來更好地理解Event Loop:

我們可以看到,主線程運(yùn)行的時(shí)候,產(chǎn)生(heap)和(stack),中的代碼調(diào)用各種外部API,它們在任務(wù)隊(duì)列中加入各種事件(click,load,done)。只要中的代碼執(zhí)行完畢,主線程就會去讀取任務(wù)隊(duì)列,依次執(zhí)行那些事件所對應(yīng)的回調(diào)函數(shù)。

五、Macrotask 和 Microtask

這是一個(gè)比較冷門的知識,在并發(fā)模型中隊(duì)列又可以分為Macrotask 和 Microtask,它們都屬于異步任務(wù)。先來看一個(gè)例子:

console.log("script start");

setTimeout(function() {
    console.log("setTimeout");
}, 0);

Promise.resolve().then(function() {
    console.log("promise1");

    setTimeout(function() {
        console.log("setTimeout in microtask");
    }, 0);
}).then(function() {
    console.log("promise2");
});

console.log("script end");

輸出:

script start
script end
promise1
promise2
setTimeout
setTimeout in microtask

Macrotask 和 Microtask有什么區(qū)別呢?

Macrotasks:setTimeout, setInterval, setImmediate, I/O, UI rendering

Microtask:process.nextTick, Promises, Object.observe(廢棄), MutationObserver

它們的執(zhí)行過程如下:

JavaScript引擎首先從macrotask queue中取出第一個(gè)任務(wù)
執(zhí)行完畢后,將microtask queue中的所有任務(wù)取出,按順序全部執(zhí)行
然后再從macrotask queue中取下一個(gè)
執(zhí)行完畢后,再次將microtask queue中的全部取出
循環(huán)往復(fù),直到兩個(gè)queue中的任務(wù)都取完

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/88472.html

相關(guān)文章

  • Javascript】探究javascript中的堆/棧/任務(wù)隊(duì)列并發(fā)模型 event loop

    摘要:而函數(shù)調(diào)用結(jié)束返回時(shí),運(yùn)行時(shí)會將棧頂?shù)恼{(diào)用結(jié)構(gòu)彈出。并發(fā)模型與引擎是單線程的,它的并發(fā)模型基于事件循環(huán)當(dāng)線程中的同步任務(wù)執(zhí)行完,執(zhí)行棧為空時(shí),則從任務(wù)隊(duì)列中取出異步任務(wù)進(jìn)行處理。在當(dāng)前的微任務(wù)沒有執(zhí)行完成時(shí),是不會執(zhí)行下一個(gè)宏任務(wù)的。 堆/棧/隊(duì)列 在javascript中,存在調(diào)用棧 (call stack)和內(nèi)存堆(memory heap) ,程序中函數(shù)依次進(jìn)入棧中等待執(zhí)行,若執(zhí)行...

    desdik 評論0 收藏0
  • 第五天 JavaScript單線程詳解

    摘要:若以多線程的方式操作這些,則可能出現(xiàn)操作的沖突。另外,因?yàn)槭菃尉€程的,在某一時(shí)刻內(nèi)只能執(zhí)行特定的一個(gè)任務(wù),并且會阻塞其它任務(wù)執(zhí)行。瀏覽器事件觸發(fā)線程事件觸發(fā)線程,當(dāng)一個(gè)事件被觸發(fā)時(shí)該線程會把事件添加到任務(wù)隊(duì)列的隊(duì)尾,等待引擎的處理。 首先,說下為什么 JavaScript 是單線程? 總所周知,JavaScript是以單線程的方式運(yùn)行的。說到線程就自然聯(lián)想到進(jìn)程。那它們有什么聯(lián)系呢? ...

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

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

    lavor 評論0 收藏0
  • 細(xì)說JavaScript單線程的一些事

    摘要:標(biāo)簽單線程首發(fā)地址碼農(nóng)網(wǎng)細(xì)說單線程的一些事最近被同學(xué)問道單線程的一些事,我竟回答不上。若以多線程的方式操作這些,則可能出現(xiàn)操作的沖突。另外,因?yàn)槭菃尉€程的,在某一時(shí)刻內(nèi)只能執(zhí)行特定的一個(gè)任務(wù),并且會阻塞其它任務(wù)執(zhí)行。 標(biāo)簽: JavaScript 單線程 首發(fā)地址:碼農(nóng)網(wǎng)《細(xì)說JavaScript單線程的一些事》 最近被同學(xué)問道 JavaScript 單線程的一些事,我竟回答不上。好...

    sarva 評論0 收藏0
  • 細(xì)說JavaScript單線程的一些事

    摘要:標(biāo)簽單線程首發(fā)地址碼農(nóng)網(wǎng)細(xì)說單線程的一些事最近被同學(xué)問道單線程的一些事,我竟回答不上。若以多線程的方式操作這些,則可能出現(xiàn)操作的沖突。另外,因?yàn)槭菃尉€程的,在某一時(shí)刻內(nèi)只能執(zhí)行特定的一個(gè)任務(wù),并且會阻塞其它任務(wù)執(zhí)行。 標(biāo)簽: JavaScript 單線程 首發(fā)地址:碼農(nóng)網(wǎng)《細(xì)說JavaScript單線程的一些事》 最近被同學(xué)問道 JavaScript 單線程的一些事,我竟回答不上。好...

    coolpail 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<