成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

js事件循環(huán)機制

wuyangnju / 2079人閱讀

摘要:為了利用多核的計算能力,提出標(biāo)準(zhǔn),允許腳本創(chuàng)建多個線程,但是子線程完全受主線程控制,且不得操作。所以,這個新標(biāo)準(zhǔn)并沒有改變單線程的本質(zhì)。

從一個例子說起
var start = new Date()

setTimeout(function () {
    var end = new Date
    console.log("Time elapsed:", end - start, "ms")
}, 500)

while (new Date() - start < 1000) {
}

有其他語言能完成預(yù)期的功能嗎?Java, 在Java.util.Timer中,對于定時任務(wù)的解決方案是通過多線程手段實現(xiàn)的,任務(wù)對象存儲在任務(wù)隊列,由專門的調(diào)度線程,在新的子線程中完成任務(wù)的執(zhí)行

js是單線程的

JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復(fù)雜的同步問題。

為了利用多核CPU的計算能力,HTML5提出Web Worker標(biāo)準(zhǔn),允許JavaScript腳本創(chuàng)建多個線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個新標(biāo)準(zhǔn)并沒有改變JavaScript單線程的本質(zhì)。

函數(shù)調(diào)用棧和任務(wù)隊列

調(diào)用棧

JS執(zhí)行時會形成調(diào)用棧,調(diào)用一個函數(shù)時,返回地址、參數(shù)、本地變量都會被推入棧中,如果當(dāng)前正在運行的函數(shù)中調(diào)用另外一個函數(shù),則該函數(shù)相關(guān)內(nèi)容也會被推入棧頂.該函數(shù)執(zhí)行完畢,則會被彈出調(diào)用棧.變量也隨之彈出,由于復(fù)雜類型值存放于堆中,因此彈出的只是指針,他們的值依然在堆中,由GC決定回收.

事件循環(huán)(event loop) & 任務(wù)隊列(task queue)

JavaScript 主線程擁有一個執(zhí)行棧以及一個任務(wù)隊列

遇到異步操作(例如:setTimeout, AJAX)時,異步操作會由瀏覽器(OS)執(zhí)行,瀏覽器會在這些任務(wù)完成后,將事先定義的回調(diào)函數(shù)推入主線程的任務(wù)隊列(task queue)中,當(dāng)主線程的執(zhí)行棧清空之后會讀取task queue中的回調(diào)函數(shù),當(dāng)task queue被讀取完畢之后,主線程接著執(zhí)行,從而進(jìn)入一個無限的循環(huán),這就是事件循環(huán).

主線程執(zhí)行棧 & 任務(wù)隊列 循環(huán)執(zhí)行,構(gòu)成事件循環(huán)

結(jié)論

setTimeout()只是將事件插入了"任務(wù)隊列",必須等到當(dāng)前代碼(執(zhí)行棧)執(zhí)行完,主線程才會去執(zhí)行它指定的回調(diào)函數(shù)。要是當(dāng)前代碼耗時很長,有可能要等很久,所以并沒有辦法保證,回調(diào)函數(shù)一定會在setTimeout()指定的時間執(zhí)行。

另一個例子
(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);
})()
Macrotask & Microtask

macrotask 和 microtask 是異步任務(wù)的兩種分類。在掛起任務(wù)時,JS 引擎會將所有任務(wù)按照類別分到這兩個隊列中,首先在 macrotask 的隊列(這個隊列也被叫做 task queue)中取出第一個任務(wù),執(zhí)行完畢后取出 microtask 隊列中的所有任務(wù)順序執(zhí)行;之后再取 macrotask 任務(wù),周而復(fù)始,直至兩個隊列的任務(wù)都取完。

macro-task: script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering

micro-task: process.nextTick, Promises(這里指瀏覽器實現(xiàn)的原生 Promise), Object.observe, MutationObserver

結(jié)論

全部代碼(script) macrotask -> microtask queue (含有promise.then) -> macrotask(setTimeout) -> 下一個microtask

Node.js的事件循環(huán) process.nextTick & setImmediate

process.nextTick指定的任務(wù)總是發(fā)生在所有異步任務(wù)之前

setImmediate指定的任務(wù)總是在下一次Event Loop時執(zhí)行

process.nextTick(function A() {
  console.log(1);
  process.nextTick(function B(){console.log(2);});
});

setTimeout(function timeout() {
  console.log("TIMEOUT FIRED");
}, 0)
new Promise(function(resolve) {
    console.log("glob1_promise");
    resolve();
}).then(function() {
    console.log("glob1_then")
})
process.nextTick(function() {
    console.log("glob1_nextTick");
})
總結(jié)

通過學(xué)習(xí)函數(shù)調(diào)用棧,任務(wù)隊列,MacroTask, MicroTask等概念,對js中的事件循環(huán)機制有更深的理解,在以后面對setTimeout, setInterval等異步操作時,更清晰的理解其運行機制,避免寫出不可控的代碼。

參考鏈接:

https://zhuanlan.zhihu.com/p/...

https://zhuanlan.zhihu.com/p/...

http://www.ruanyifeng.com/blo...

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

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

相關(guān)文章

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

    摘要:主線程不斷重復(fù)上面的三步,此過程也就是常說的事件循環(huán)。所以主線程代碼執(zhí)行時間過長,會阻塞事件循環(huán)的執(zhí)行。參考資料這一次,徹底弄懂執(zhí)行機制任務(wù)隊列的順序機制事件循環(huán)搞懂異步事件輪詢與中的事件循環(huán) 1. 說明 讀過本文章后,您能知道: JavaScript代碼在瀏覽器中的執(zhí)行機制和事件循環(huán) 面試中經(jīng)常遇到的代碼輸出順序問題 首先通過一段代碼來驗證你是否了解代碼輸出順序,如果你不知道輸出...

    Ververica 評論0 收藏0
  • Js事件循環(huán)(Event Loop)機制以及實例講解

    摘要:主線程要明確的一點是,主線程跟執(zhí)行棧是不同概念,主線程規(guī)定現(xiàn)在執(zhí)行執(zhí)行棧中的哪個事件。主線程循環(huán)即主線程會不停的從執(zhí)行棧中讀取事件,會執(zhí)行完所有棧中的同步代碼。以上參考資料詳解中的事件循環(huán)機制中的事件循環(huán)運行機制詳解再談 showImg(https://segmentfault.com/img/remote/1460000015317437?w=1920&h=1080); 前言 大家都...

    Anshiii 評論0 收藏0
  • 【Node.js】理解事件循環(huán)機制

    摘要:前沿是基于引擎的運行環(huán)境具有事件驅(qū)動非阻塞等特點結(jié)合具有網(wǎng)絡(luò)編程文件系統(tǒng)等服務(wù)端的功能用庫進(jìn)行異步事件處理線程的單線程含義實際上說的是執(zhí)行同步代碼的主線程一個程序的啟動不止是分配了一個線程,而是我們只能在一個線程執(zhí)行代碼當(dāng)出現(xiàn)資源調(diào)用連接等 前沿 Node.js 是基于V8引擎的javascript運行環(huán)境. Node.js具有事件驅(qū)動, 非阻塞I/O等特點. 結(jié)合Node API, ...

    Riddler 評論0 收藏0
  • JS瀏覽器事件循環(huán)機制

    摘要:事件循環(huán)機制事件循環(huán)機制分為瀏覽器和事件循環(huán)機制,兩者的實現(xiàn)技術(shù)不一樣,瀏覽器是中定義的規(guī)范,是由庫實現(xiàn)。整個事件循環(huán)完成之后,會去檢測微任務(wù)的任務(wù)隊列中是否存在任務(wù),存在就執(zhí)行。 文章來自我的 github 博客,包括技術(shù)輸出和學(xué)習(xí)筆記,歡迎star。 先來明白些概念性內(nèi)容。 進(jìn)程、線程 進(jìn)程是系統(tǒng)分配的獨立資源,是 CPU 資源分配的基本單位,進(jìn)程是由一個或者多個線程組成的。 線...

    zebrayoung 評論0 收藏0
  • 淺談不同環(huán)境下的JavaScript執(zhí)行機制 + 示例詳解

    摘要:如果沒有其他異步任務(wù)要處理比如到期的定時器,會一直停留在這個階段,等待請求返回結(jié)果。執(zhí)行的執(zhí)行事件關(guān)閉請求的,例如事件循環(huán)的每一次循環(huán)都需要依次經(jīng)過上述的階段。因此,才會早于執(zhí)行。 showImg(https://segmentfault.com/img/bVbnY76); 概念 同步任務(wù)(Synchronous) 在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù) ...

    wanghui 評論0 收藏0
  • JS JavaScript事件循環(huán)機制

    摘要:事件循環(huán)機制首先區(qū)分進(jìn)程和線程進(jìn)程是資源分配的最小單位系統(tǒng)會給它分配內(nèi)存不同的進(jìn)程之間是可以同學(xué)的,如管道命名管道消息隊列一個進(jìn)程里有單個或多個線程瀏覽器是多進(jìn)程的,因為系統(tǒng)給它的進(jìn)程分配了資源內(nèi)存打開會有一個主進(jìn)程,每打開一個頁就有一個獨 JS JavaScript事件循環(huán)機制 首先區(qū)分進(jìn)程和線程 進(jìn)程是cpu資源分配的最小單位(系統(tǒng)會給它分配內(nèi)存) 不同的進(jìn)程之間是可以同學(xué)的,如...

    dantezhao 評論0 收藏0

發(fā)表評論

0條評論

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