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

資訊專(zhuān)欄INFORMATION COLUMN

深入理解 Event Loop

Carbs / 2226人閱讀

摘要:即使現(xiàn)在支持,由于沒(méi)有多線程的機(jī)制,和執(zhí)行線程只能通過(guò)來(lái)通信,而且由于沒(méi)有鎖,無(wú)法訪問(wèn)和對(duì)象。的單線程是指一個(gè)瀏覽器進(jìn)程中只有一個(gè)的執(zhí)行線程,即同一時(shí)刻內(nèi)只會(huì)有一段代碼在執(zhí)行。與單線程如何實(shí)現(xiàn)異步設(shè)計(jì)了一個(gè)事件循環(huán)的方式。

眾所周知,JavaScript(以下簡(jiǎn)稱(chēng) JS) 是單線程語(yǔ)言,在 html5 中增加了 web workers,web workers 是新開(kāi)了線程執(zhí)行的,那么 JS 還是單線程的嗎?當(dāng)然是,為什么要設(shè)計(jì)成單線程?

網(wǎng)上有很多說(shuō)法,大部分都說(shuō)是多個(gè)線程同時(shí)對(duì)一個(gè)dom操作(同時(shí)修改dom內(nèi)容,一個(gè)線程增加屬性,一個(gè)線程刪除屬性),會(huì)非常混亂,當(dāng)然如果支持多線程就會(huì)相應(yīng)的就要加入多線程的鎖機(jī)制,那么 JS 就變得非常復(fù)雜了,想想 JS 最開(kāi)始設(shè)計(jì)的初衷就是用于用戶(hù)交互,而且當(dāng)時(shí)的原始需求是:功能不需要太強(qiáng),語(yǔ)法較為簡(jiǎn)單,容易學(xué)習(xí)和部署,Brendan Eich 只用了10天,就設(shè)計(jì)完成了這種語(yǔ)言的第一版,因此也不可能加入多線程這么復(fù)雜的技術(shù)。

即使現(xiàn)在支持 web workers,由于沒(méi)有多線程的機(jī)制,web workers 和執(zhí)行線程只能通過(guò) postMessage 來(lái)通信,而且由于沒(méi)有鎖,web workers 無(wú)法訪問(wèn) window 和 document 對(duì)象。

JS 的單線程是指一個(gè)瀏覽器進(jìn)程中只有一個(gè) JS 的執(zhí)行線程,即同一時(shí)刻內(nèi)只會(huì)有一段代碼在執(zhí)行。

Micro-Task 與 Macro-Task

單線程如何實(shí)現(xiàn)異步?JS 設(shè)計(jì)了一個(gè)事件循環(huán)的方式。所有的代碼執(zhí)行均按照事件循環(huán)的方式進(jìn)行。

事件循環(huán)中分兩種任務(wù):一個(gè)是宏任務(wù)(Macro-Task),另一個(gè)是微任務(wù)(Micro-Task)。常見(jiàn)的宏任務(wù)和微任務(wù)如下。

宏任務(wù):script(整體代碼)、setTimeout、setInterval、requestAnimationFrame、I/O、事件、MessageChannel、setImmediate (Node.js) 微任務(wù):Promise.then、 MutaionObserver、process.nextTick (Node.js)

事件循環(huán)按下圖的方式進(jìn)行。

注意: 宏任務(wù)執(zhí)行完后,需要清空當(dāng)前微任務(wù)隊(duì)列后才回去執(zhí)行下一個(gè)宏任務(wù),如果微任務(wù)里面產(chǎn)生了新的微任務(wù),仍然會(huì)在當(dāng)前事件循環(huán)里面被執(zhí)行完,后面會(huì)舉例說(shuō)明。

來(lái)個(gè)示例驗(yàn)證下上面的流程。

<script>
    console.log(1);

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

    Promise.resolve().then(function promise1() {
        console.log(3);
        setTimeout(function timeout2() {
            console.log(4);
            Promise.resolve().then(function promise2() {
                console.log(5);
            });
        }, 0);
        return Promise.resolve()
            .then(function promise3() {
                console.log(6);
                return Promise.resolve().then(function promise4() {
                    console.log(7);
                });
            })
            .then(function promise5() {
                console.log(8);
            });
    })
    console.log(9);
script>

<script>
    console.log(10);
    setTimeout(function timeout3() {
        console.log(11);
    }, 0);
    Promise.resolve().then(function promise6() {
        console.log(12);
    });
script>

按照上面流程梳理下執(zhí)行流程:

    將兩個(gè)宏任務(wù)(兩個(gè)script代碼)初始化進(jìn)宏任務(wù)隊(duì)列,宏任務(wù)隊(duì)列為:[script1, script2]

    script1 出隊(duì)壓入執(zhí)行棧執(zhí)行,宏任務(wù)隊(duì)列為:[script2]

    同步代碼執(zhí)行輸出:1,

    timeout1 入隊(duì),宏任務(wù)隊(duì)列為:[script2, timeout1]

    promise1 入隊(duì),微任務(wù)隊(duì)列為:[promise1]

    同步代碼執(zhí)行輸出:9

    script1 執(zhí)行完畢,進(jìn)入微任務(wù)執(zhí)行階段,promise1 出隊(duì)壓入執(zhí)行棧執(zhí)行,微任務(wù)隊(duì)列為空

    同步代碼執(zhí)行輸出:3

    timeout2 入隊(duì),宏任務(wù)隊(duì)列為:[script2, timeout1, timeout2]

    promise3 入隊(duì),微任務(wù)隊(duì)列為:[promise3]

    promise1 執(zhí)行完畢,繼續(xù)判斷微任務(wù)隊(duì)列是否為空,promise3 出隊(duì)壓入執(zhí)行棧執(zhí)行,微任務(wù)隊(duì)列為空

    同步代碼執(zhí)行輸出:6

    promise4 入隊(duì),微任務(wù)隊(duì)列為:[promise4]

    promise3 執(zhí)行完畢,promise5 入隊(duì),微任務(wù)隊(duì)列為:[promise4,promise5]

    判斷微任務(wù)隊(duì)列是否為空,promise4 出隊(duì)壓入執(zhí)行棧執(zhí)行,微任務(wù)隊(duì)列為:[promise5]

    同步代碼執(zhí)行輸出:7

    promise4 執(zhí)行完畢,繼續(xù)判斷微任務(wù)隊(duì)列是否為空,promise5 出隊(duì)壓入執(zhí)行棧執(zhí)行,微任務(wù)隊(duì)列為空

    同步代碼執(zhí)行輸出:8

    微任務(wù)隊(duì)列清空,宏任務(wù) script2 出隊(duì)壓入執(zhí)行棧執(zhí)行,宏任務(wù)隊(duì)列為[ timeout1, timeout2]

    同步代碼執(zhí)行輸出:10

    timeout3 入隊(duì),宏任務(wù)隊(duì)列為:[timeout1, timeout2, timeout3]

    promise6 入隊(duì),微任務(wù)隊(duì)列為:[promise6]

    script2 執(zhí)行完畢,進(jìn)入微任務(wù)執(zhí)行階段,promise6 出隊(duì)壓入執(zhí)行棧執(zhí)行,微任務(wù)隊(duì)列為空

    同步代碼執(zhí)行輸出:12

    微任務(wù)隊(duì)列為空,執(zhí)行宏任務(wù)隊(duì)列,timeout1 判斷是否到時(shí)間,timeout1 到時(shí)壓入執(zhí)行棧執(zhí)行,宏任務(wù)隊(duì)列為[ timeout2, timeout3]

    同步代碼執(zhí)行輸出:2

    微任務(wù)隊(duì)列為空,執(zhí)行宏任務(wù)隊(duì)列,timeout2 判斷是否到時(shí)間,timeout2 到時(shí)壓入執(zhí)行棧執(zhí)行,宏任務(wù)隊(duì)列為[ timeout3]

    同步代碼執(zhí)行輸出:4,promise2 入隊(duì),微任務(wù)隊(duì)列為:[promise2]

    timeout2 執(zhí)行完畢,判斷微任務(wù)隊(duì)列是否為空,promise2 出隊(duì)壓入執(zhí)行棧執(zhí)行,微任務(wù)隊(duì)列為空

    同步代碼執(zhí)行輸出:5

    微任務(wù)隊(duì)列為空,執(zhí)行宏任務(wù)隊(duì)列,timeout3 判斷是否到時(shí)間,timeout3 到時(shí)壓入執(zhí)行棧執(zhí)行,宏任務(wù)隊(duì)列為空

    同步代碼執(zhí)行輸出:11

    宏任務(wù)隊(duì)列為空

參考

JavaScript語(yǔ)言的歷史

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

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

相關(guān)文章

  • 深入理解js引擎的執(zhí)行機(jī)制

    摘要:深入理解引擎的執(zhí)行機(jī)制最近在反省,很多知識(shí)都是只會(huì)用,不理解底層的知識(shí)。在閱讀之前,請(qǐng)先記住兩點(diǎn)是單線程語(yǔ)言的是的執(zhí)行機(jī)制。所以,是存在異步執(zhí)行的,比如單線程是怎么實(shí)現(xiàn)異步的場(chǎng)景描述通過(guò)事件循環(huán),所以說(shuō),理解了機(jī)制,也就理解了的執(zhí)行機(jī)制啦。 深入理解js引擎的執(zhí)行機(jī)制 最近在反省,很多知識(shí)都是只會(huì)用,不理解底層的知識(shí)。所以在開(kāi)發(fā)過(guò)程中遇到一些奇怪的比較難解決的bug,在思考的時(shí)候就會(huì)收...

    feng409 評(píng)論0 收藏0
  • 10分鐘理解JS引擎的執(zhí)行機(jī)制

    摘要:深入理解引擎的執(zhí)行機(jī)制靈魂三問(wèn)為什么是單線程的為什么需要異步單線程又是如何實(shí)現(xiàn)異步的呢中的中的說(shuō)說(shuō)首先請(qǐng)牢記點(diǎn)是單線程語(yǔ)言的是的執(zhí)行機(jī)制。 深入理解JS引擎的執(zhí)行機(jī)制 1.靈魂三問(wèn) : JS為什么是單線程的? 為什么需要異步? 單線程又是如何實(shí)現(xiàn)異步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.說(shuō)說(shuō)setTimeout 首先,請(qǐng)牢記2...

    zzbo 評(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
  • 【轉(zhuǎn)】深入理解JS單線程機(jī)制【原文作者:MasterYao】

    摘要:的單線程,與它的用途有關(guān)。只要指定過(guò)回調(diào)函數(shù),這些事件發(fā)生時(shí)就會(huì)進(jìn)入任務(wù)隊(duì)列,等待主線程讀取。四主線程從任務(wù)隊(duì)列中讀取事件,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱(chēng)為事件循環(huán)。令人困惑的是,文檔中稱(chēng),指定的回調(diào)函數(shù),總是排在前面。 原文:http://www.cnblogs.com/Master... 一、為什么JavaScript是單線程? JavaScript語(yǔ)言的一大特點(diǎn)...

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

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

    codeGoogle 評(píng)論0 收藏0
  • Javascript事件循環(huán)入門(mén)到“忘記”(一).md

    摘要:中叫做調(diào)用棧先進(jìn)后出,后進(jìn)先出。如下圖這是典型的內(nèi)存溢出,可能會(huì)出現(xiàn)在某些場(chǎng)景下需要遞歸,但業(yè)務(wù)邏輯中的判斷又沒(méi)能正常計(jì)算進(jìn)入到預(yù)設(shè)情況,于是調(diào)用棧中不斷進(jìn)入,又無(wú)法執(zhí)行完,就造成內(nèi)存溢出了。 本文主要介紹Javascript事件循環(huán)在瀏覽器上的一些特性和應(yīng)用介紹。 Javascript小知識(shí) JavaScript的并發(fā)模型基于事件循環(huán)(Event Loop)。這個(gè)模型與像C或者Jav...

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

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

0條評(píng)論

閱讀需要支付1元查看
<