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

資訊專(zhuān)欄INFORMATION COLUMN

麻煩把JS的事件環(huán)給我安排一下!??!

layman / 2697人閱讀

摘要:上一輪循環(huán)中有少數(shù)的會(huì)被延遲到這一輪的這一階段執(zhí)行。執(zhí)行,在適當(dāng)?shù)臈l件下會(huì)阻塞在這個(gè)階段執(zhí)行設(shè)定的回調(diào)。

上次大家跟我吃飽喝足又?jǐn)]了一遍PromiseA+,想必大家肯定滿(mǎn)腦子想的都是西瓜可樂(lè)......

什么西瓜可樂(lè)!明明是Promise!

呃,清醒一下,今天大家搬個(gè)小板凳,聽(tīng)我說(shuō)說(shuō)JS中比較有意思的事件環(huán),在了解事件環(huán)之前呢,我們先來(lái)了解幾個(gè)基本概念。

棧(Stack)
棧是一種遵循后進(jìn)先出(LIFO)的數(shù)據(jù)集合,新添加或待刪除的元素都保存在棧的末尾,稱(chēng)作棧頂,另一端稱(chēng)作棧底。在棧里,新元素都靠近棧頂,舊元素都接近棧底

感覺(jué)說(shuō)起來(lái)并不是很好理解,我們舉個(gè)例子,比如有一個(gè)乒乓球盒,我們不停的向球盒中放進(jìn)乒乓球,那么最先放進(jìn)去的乒乓球一定是在最下面,最后放進(jìn)去的一定是在最上面,那么如果我們想要把這些球取出來(lái)是不是就必須依次從上到下才能拿出來(lái),這個(gè)模型就是后進(jìn)先出,就是我們后進(jìn)入球盒的球反而最先出來(lái)。

棧的概念其實(shí)在我們js中十分的重要,大家都知道我們js是一個(gè)單線程語(yǔ)言,那么他單線程在哪里呢,就在他的主工作線程,也就是我們常說(shuō)的執(zhí)行上下文,這個(gè)執(zhí)行上下文就是??臻g,我們來(lái)看一段代碼:

 console.log("1");
 function a(){
    console.log("2");
    function b(){
        console.log("3")
    }
    b()
 }
 a()
 

我們知道函數(shù)執(zhí)行的時(shí)候會(huì)將這個(gè)函數(shù)放入到我們的執(zhí)行上下文中,當(dāng)函數(shù)執(zhí)行完畢之后會(huì)彈出執(zhí)行棧,那么根據(jù)這個(gè)原理我們就能知道這段代碼的運(yùn)行過(guò)程是

首先我們代碼執(zhí)行的時(shí)候會(huì)有一個(gè)全局上下文,此時(shí)代碼運(yùn)行,全局上下文進(jìn)行執(zhí)行棧,處在棧底的位置

我們遇到console.log("1"),這個(gè)函數(shù)在調(diào)用的時(shí)候進(jìn)入執(zhí)行棧,當(dāng)這句話(huà)執(zhí)行完畢也就是到了下一行的時(shí)候我們console這個(gè)函數(shù)就會(huì)出棧,此時(shí)棧中仍然只有全局上下文

接著運(yùn)行代碼,這里注意的是我們遇到的函數(shù)聲明都不會(huì)進(jìn)入執(zhí)行棧,只有當(dāng)我們的函數(shù)被調(diào)用被執(zhí)行的時(shí)候才會(huì)進(jìn)入,這個(gè)原理和我們執(zhí)行棧的名字也就一模一樣,接著我們遇到了a();這句代碼這個(gè)時(shí)候我們的a函數(shù)就進(jìn)入了執(zhí)行棧,然后進(jìn)入到我們a的函數(shù)內(nèi)部中,此時(shí)我們的函數(shù)執(zhí)行棧應(yīng)該是 全局上下文 —— a

接著我運(yùn)行console.log("2"),執(zhí)行棧變成 全局上下文——a——console,接著我們的console運(yùn)行完畢,我們執(zhí)行?;謴?fù)成全局上下文 —— a

接著我們遇到了b();那么b進(jìn)入我們的執(zhí)行棧,全局上下文——a——b,

接著進(jìn)入b函數(shù)的內(nèi)部,執(zhí)行console.log("3")的時(shí)候執(zhí)行棧為全局上下文——a——b——console,執(zhí)行完畢之后回復(fù)成全局上下文——a——b

然后我們的b函數(shù)就執(zhí)行完畢,然后就被彈出執(zhí)行棧,那么執(zhí)行棧就變成全局上下文——a

然后我們的a函數(shù)就執(zhí)行完畢,然后就被彈出執(zhí)行棧,那么執(zhí)行棧就變成全局上下文

然后我們的全局上下文會(huì)在我們的瀏覽器關(guān)閉的時(shí)候出棧

我們的執(zhí)行上下文的執(zhí)行過(guò)程就是這樣,是不是清楚了很多~

通過(guò)上面的執(zhí)行上下文我們可以發(fā)現(xiàn)幾個(gè)特點(diǎn):

執(zhí)行上下文是單線程

執(zhí)行上下文是同步執(zhí)行代碼

當(dāng)有函數(shù)被調(diào)用的時(shí)候,這個(gè)函數(shù)會(huì)進(jìn)入執(zhí)行上下文

代碼運(yùn)行會(huì)產(chǎn)生一個(gè)全局的上下文,只有當(dāng)瀏覽器關(guān)閉才會(huì)出棧

隊(duì)列(Queue)
隊(duì)列是一種遵循先進(jìn)先出(FIFO)的數(shù)據(jù)集合,新的條目會(huì)被加到隊(duì)列的末尾,舊的條目會(huì)從隊(duì)列的頭部被移出。

這里我們可以看到隊(duì)列和棧不同的地方是棧是后進(jìn)先出類(lèi)似于乒乓球盒,而隊(duì)列是先進(jìn)先出,也就是說(shuō)最先進(jìn)入的會(huì)最先出去。
同樣我們舉個(gè)例子,隊(duì)列就好比是我們排隊(duì)過(guò)安檢,最先來(lái)到的人排在隊(duì)伍的首位,后來(lái)的人接著排在隊(duì)伍的后面,然后安檢員會(huì)從隊(duì)伍的首端進(jìn)行安檢,檢完一個(gè)人就放行一個(gè)人,是不是這樣的一個(gè)隊(duì)伍就是先進(jìn)先出的一個(gè)過(guò)程。

隊(duì)列這里我們就要提到兩個(gè)概念,宏任務(wù)(macro task),微任務(wù)(micro task)。

任務(wù)隊(duì)列

Js的事件執(zhí)行分為宏仁務(wù)和微任務(wù)

宏仁務(wù)主要是由script(全局任務(wù)),setTimeoutsetIntervalsetImmediate ,I/O ,UI rendering

微任務(wù)主要是process.nextTick, Promise.then, Object.observer, MutationObserver.

瀏覽器事件環(huán)

js執(zhí)行代碼的過(guò)程中如果遇到了上述的任務(wù)代碼之后,會(huì)先把這些代碼的回調(diào)放入對(duì)應(yīng)的任務(wù)隊(duì)列中去,然后繼續(xù)執(zhí)行主線程的代碼知道執(zhí)行上下文中的函數(shù)全部執(zhí)行完畢了之后,會(huì)先去微任務(wù)隊(duì)列中執(zhí)行相關(guān)的任務(wù),微任務(wù)隊(duì)列清空之后,在從宏仁務(wù)隊(duì)列中拿出任務(wù)放到執(zhí)行上下文中,然后繼續(xù)循環(huán)。

執(zhí)行代碼,遇到宏仁務(wù)放入宏仁務(wù)隊(duì)列,遇到微任務(wù)放入微任務(wù)隊(duì)列,執(zhí)行其他函數(shù)的時(shí)候放入執(zhí)行上下文

執(zhí)行上下文中全部執(zhí)行完畢后,執(zhí)行微任務(wù)隊(duì)列

微任務(wù)隊(duì)列執(zhí)行完畢后,再到宏仁務(wù)隊(duì)列中取出第一項(xiàng)放入執(zhí)行上下文中執(zhí)行

接著就不停循環(huán)1-3的步驟,這就是瀏覽器環(huán)境中的js事件環(huán)

    //學(xué)了上面的事件環(huán) 我們來(lái)看一道面試題
    setTimeout(function () {
      console.log(1);
    }, 0);
    
    Promise.resolve(function () {
      console.log(2);
    })
    
    new Promise(function (resolve) {
      console.log(3);
    });
    
    console.log(4);
    
    //上述代碼的輸出結(jié)果是什么???

思考思考思考思考~~~

正確答案是3 4 1,是不是和你想的一樣?我們來(lái)看一下代碼的運(yùn)行流程

    // 遇到setTimeout 將setTimeout回調(diào)放入宏仁務(wù)隊(duì)列中
    setTimeout(function () {
      console.log(1);
    }, 0);
    // 遇到了promise,但是并沒(méi)有then方法回調(diào) 所以這句代碼會(huì)在執(zhí)行過(guò)程中進(jìn)入我們當(dāng)前的執(zhí)行上下文 緊接著就出棧了
    Promise.resolve(function () {
      console.log(2);
    })
    // 遇到了一個(gè) new Promise,不知道大家還記不記得我們上一篇文章中講到Promise有一個(gè)原則就是在初始化Promise的時(shí)候Promise內(nèi)部的構(gòu)造器函數(shù)會(huì)立即執(zhí)行 因此 在這里會(huì)立即輸出一個(gè)3,所以這個(gè)3是第一個(gè)輸入的
    new Promise(function (resolve) {
      console.log(3);
    });
    // 然后輸入第二個(gè)輸出4  當(dāng)代碼執(zhí)行完畢后回去微任務(wù)隊(duì)列查找有沒(méi)有任務(wù),發(fā)現(xiàn)微任務(wù)隊(duì)列是空的,那么就去宏仁務(wù)隊(duì)列中查找,發(fā)現(xiàn)有一個(gè)我們剛剛放進(jìn)去的setTimeout回調(diào)函數(shù),那么就取出這個(gè)任務(wù)進(jìn)行執(zhí)行,所以緊接著輸出1
    console.log(4);

看到上述的講解,大家是不是都明白了,是不是直呼簡(jiǎn)單~

那我們接下來(lái)來(lái)看看node環(huán)境中的事件執(zhí)行環(huán)

NodeJs 事件環(huán)

瀏覽器的 Event Loop 遵循的是 HTML5 標(biāo)準(zhǔn),而 NodeJs 的 Event Loop 遵循的是 libuv標(biāo)準(zhǔn),因此呢在事件的執(zhí)行中就會(huì)有一定的差異,大家都知道nodejs其實(shí)是js的一種runtime,也就是運(yùn)行環(huán)境,那么在這種環(huán)境中nodejs的api大部分都是通過(guò)回調(diào)函數(shù),事件發(fā)布訂閱的方式來(lái)執(zhí)行的,那么在這樣的環(huán)境中我們代碼的執(zhí)行順序究竟是怎么樣的呢,也就是我們不同的回調(diào)函數(shù)究竟是怎么分類(lèi)的然后是按照什么順序執(zhí)行的,其實(shí)就是由我們的libuv所決定的。

                   ┌───────────────────────────┐
                ┌─>│           timers          │
                │  └─────────────┬─────────────┘
                │  ┌─────────────┴─────────────┐
                │  │     pending callbacks     │
                │  └─────────────┬─────────────┘
                │  ┌─────────────┴─────────────┐
                │  │       idle, prepare       │
                │  └─────────────┬─────────────┘      ┌───────────────┐
                │  ┌─────────────┴─────────────┐      │   incoming:   │
                │  │           poll            │<─────┤  connections, │
                │  └─────────────┬─────────────┘      │   data, etc.  │
                │  ┌─────────────┴─────────────┐      └───────────────┘
                │  │           check           │
                │  └─────────────┬─────────────┘
                │  ┌─────────────┴─────────────┐
                └──┤      close callbacks      │
                   └───────────────────────────┘

我們先來(lái)看下這六個(gè)任務(wù)是用來(lái)干什么的

timers: 這個(gè)階段執(zhí)行setTimeout()和setInterval()設(shè)定的回調(diào)。

pending callbacks: 上一輪循環(huán)中有少數(shù)的 I/O callback會(huì)被延遲到這一輪的這一階段執(zhí)行。

idle, prepare: 僅內(nèi)部使用。

poll: 執(zhí)行 I/O callback,在適當(dāng)?shù)臈l件下會(huì)阻塞在這個(gè)階段

check: 執(zhí)行setImmediate()設(shè)定的回調(diào)。

close callbacks: 執(zhí)行比如socket.on("close", ...)的回調(diào)。

我們?cè)賮?lái)看網(wǎng)上找到的一張nodejs執(zhí)行圖,我們能看到圖中有六個(gè)步驟 ,當(dāng)代碼執(zhí)行中如果我們遇到了這六個(gè)步驟中的回調(diào)函數(shù),就放入對(duì)應(yīng)的隊(duì)列中,然后當(dāng)我們同步人物執(zhí)行完畢的時(shí)候就會(huì)切換到下一個(gè)階段,也就是timer階段,然后timer階段執(zhí)行過(guò)程中會(huì)把這個(gè)階段的所有回調(diào)函數(shù)全部執(zhí)行了然后再進(jìn)入下一個(gè)階段,需要注意的是我們?cè)诿看坞A段發(fā)生切換的時(shí)候都會(huì)先執(zhí)行一次微任務(wù)隊(duì)列中的所有任務(wù),然后再進(jìn)入到下一個(gè)任務(wù)階段中去,所以我們就能總結(jié)出nodejs的事件環(huán)順序

同步代碼執(zhí)行,清空微任務(wù)隊(duì)列,執(zhí)行timer階段的回調(diào)函數(shù)(也就是setTimeout,setInterval)

全部執(zhí)行完畢,清空微任務(wù)隊(duì)列,執(zhí)行pending callbacks階段的回調(diào)函數(shù)

全部執(zhí)行完畢,清空微任務(wù)隊(duì)列,執(zhí)行idle, prepare階段的回調(diào)函數(shù)

全部執(zhí)行完畢,清空微任務(wù)隊(duì)列,執(zhí)行poll階段的回調(diào)函數(shù)

全部執(zhí)行完畢,清空微任務(wù)隊(duì)列,執(zhí)行check階段的回調(diào)函數(shù)(也就是setImmediate)

全部執(zhí)行完畢,清空微任務(wù)隊(duì)列,執(zhí)行close callbacks階段的回調(diào)函數(shù)

然后循環(huán)1-6階段

那我們來(lái)練練手~~~

    // 我們來(lái)對(duì)著我們的執(zhí)行階段看看
    let fs = require("fs");
    // 遇到setTimeout 放入timer回調(diào)中
    setTimeout(function(){
        Promise.resolve().then(()=>{
            console.log("then1");
        })
    },0);
    // 放入微任務(wù)隊(duì)列中
    Promise.resolve().then(()=>{
        console.log("then2");
    });
    // i/o操作 放入pending callbacks回調(diào)中
    fs.readFile("./text.md",function(){
        // 放入check階段
        setImmediate(()=>{
            console.log("setImmediate")
        });
        // 放入微任務(wù)隊(duì)列中
        process.nextTick(function(){
            console.log("nextTick")
        })
    });

首先同步代碼執(zhí)行完畢,我們先清空微任務(wù),此時(shí)輸出then2,然后切換到timer階段,執(zhí)行timer回調(diào),輸出then1,然后執(zhí)行i/o操作回調(diào),然后清空微任務(wù)隊(duì)列,輸出nextTick,接著進(jìn)入check階段,清空check階段回調(diào)輸出setImmediate

所有的規(guī)則看著都云里霧里,但是呢只要我們總結(jié)出來(lái)了規(guī)律,理解了他們的運(yùn)行機(jī)制那么我們就掌握了這些規(guī)則,好咯,今天又學(xué)了這么多,不說(shuō)了不說(shuō)了,趕緊滾去寫(xiě)業(yè)務(wù)代碼了.............

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

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

相關(guān)文章

  • js異同步

    摘要:完成請(qǐng)問(wèn)應(yīng)該如何安排操作流程上面代碼采用個(gè)回調(diào)函數(shù)的嵌套,不僅寫(xiě)起來(lái)麻煩,容易出錯(cuò),而且難以維護(hù)串行執(zhí)行我們可以編寫(xiě)一個(gè)流程控制函數(shù),讓它來(lái)控制異步任務(wù),一個(gè)任務(wù)完成以后,再執(zhí)行另一個(gè)。 前言 回調(diào)地獄showImg(https://segmentfault.com/img/remote/1460000011554165?w=1000&h=710); js異步 Javascript 語(yǔ)...

    leanxi 評(píng)論0 收藏0
  • node核心特性理解

    摘要:概述本文主要介紹了我對(duì)的一些核心特性的理解,包括架構(gòu)特點(diǎn)機(jī)制核心模塊與簡(jiǎn)單應(yīng)用。在此期間,主線程繼續(xù)執(zhí)行其他任務(wù)。延續(xù)了瀏覽器端單線程,只用一個(gè)主線程執(zhí)行,不斷循環(huán)遍歷事件隊(duì)列,執(zhí)行事件。 原文地址在我的博客,轉(zhuǎn)載請(qǐng)注明來(lái)源,謝謝! node是在前端領(lǐng)域經(jīng)??吹降脑~。node對(duì)于前端的重要性已經(jīng)不言而喻,掌握node也是作為合格的前端工程師一項(xiàng)基本功了。知道node、知道后端的一些東西...

    huangjinnan 評(píng)論0 收藏0
  • 一個(gè)主板維修大佬轉(zhuǎn)行Java成長(zhǎng)經(jīng)歷,心酸......

    摘要:考慮了一段時(shí)間之后,終于鼓起勇氣找到老板離了職,去了一個(gè)北京的某培訓(xùn)機(jī)構(gòu),進(jìn)行了個(gè)月的加工,每天學(xué)習(xí)到凌晨點(diǎn),新鮮出爐,滿(mǎn)懷信心的去面試。 12年高中畢業(yè)后,因高考失誤而停止學(xué)業(yè),轉(zhuǎn)戰(zhàn)維修行業(yè),在經(jīng)過(guò)3月的培訓(xùn)從小白成長(zhǎng)維修大佬,在筆記本維修行業(yè)中摸爬滾打了,近3年也算是在行業(yè)中小有名氣,日子過(guò)得十分悠閑,每當(dāng)修好一片主板那種喜悅無(wú)法表達(dá)。 showImg(https://segmen...

    tinyq 評(píng)論0 收藏0
  • vue -- 非父子組件傳值,事件總線(eventbus)使用方式

    摘要:我的個(gè)人博客地址資源地址非父子組件傳值,事件總線的使用方式我的博客地址如果您對(duì)我的博客內(nèi)容有疑惑或質(zhì)疑的地方,請(qǐng)?jiān)谙路皆u(píng)論區(qū)留言,或郵件給我,共同學(xué)習(xí)進(jìn)步。 歡迎訪問(wèn)我的個(gè)人博客:http://www.xiaolongwu.cn 前言 先說(shuō)一下什么是事件總線,其實(shí)就是訂閱發(fā)布者模式; 比如有一個(gè)bus對(duì)象,這個(gè)對(duì)象上有兩個(gè)方法,一個(gè)是on(監(jiān)聽(tīng),也就是訂閱),一個(gè)是emit(觸發(fā),也就...

    zone 評(píng)論0 收藏0
  • 春招:我居然三天就拿到了offer?

    摘要:算法名稱(chēng)描述優(yōu)點(diǎn)缺點(diǎn)標(biāo)記清除算法暫停除了線程以外的所有線程算法分為標(biāo)記和清除兩個(gè)階段首1 回顧我的時(shí)間線 在本文的開(kāi)頭,先分享一下自己的春招經(jīng)歷吧: 各位掘友大家好,我是練習(xí)時(shí)長(zhǎng)快一年的Android小蔡雞,喜歡看源碼,逛掘金,寫(xiě)技術(shù)文章...... 好了好,不開(kāi)玩笑了OWO,今年春招投了許多簡(jiǎn)歷的,但是被撈的只有阿里,頭條和美團(tuán),一路下來(lái)挺不容易的. 個(gè)人認(rèn)為在春招中運(yùn)氣>性格>三觀>技術(shù)...

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

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

0條評(píng)論

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