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

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript疑難雜癥系列-事件循環(huán)

Keagan / 3641人閱讀

摘要:而之后事件循環(huán)一直會(huì)去遍歷任務(wù)隊(duì)列,一旦有任務(wù)放入就會(huì)放入主線(xiàn)程中執(zhí)行。任務(wù)隊(duì)列所謂任務(wù)是返回的一個(gè)個(gè)通知,讓主線(xiàn)程在讀取任務(wù)隊(duì)列的時(shí)候得知這個(gè)異步任務(wù)已經(jīng)完成,下一步該執(zhí)行這個(gè)任務(wù)的回調(diào)函數(shù)了。

javascript單線(xiàn)程
瀏覽器端,復(fù)雜的UI環(huán)境會(huì)限制多線(xiàn)程語(yǔ)言的開(kāi)發(fā)。
例如,一個(gè)線(xiàn)程在操作一個(gè)DOM元素時(shí),另一個(gè)線(xiàn)程需要去刪除DOM元素,
這個(gè)之間就需要進(jìn)行狀態(tài)的同步,何況前端可能不止操作這么一個(gè)DOM元素。
所以,為了避免在開(kāi)發(fā)過(guò)程中,去進(jìn)行復(fù)雜的同步,選用單線(xiàn)程語(yǔ)言進(jìn)行開(kāi)發(fā)是最好的解決方案
棧就是和列表類(lèi)似的一種數(shù)據(jù)結(jié)構(gòu),它可以用來(lái)解決計(jì)算機(jī)世界里很多的問(wèn)題。棧是一種高效的數(shù)據(jù)結(jié)構(gòu),因?yàn)閿?shù)據(jù)只能在棧頂添加或刪除,所以這樣的操作很快,而且容易實(shí)現(xiàn)。
棧的使用遍布程序語(yǔ)言的方方面面,從表達(dá)式求值到處理函數(shù)調(diào)用; 函數(shù)調(diào)用形成了一個(gè)棧幀
具有一種后入先出(LIFO,last-in-first-out)的數(shù)據(jù)結(jié)構(gòu)
由于棧具有后入先出的特點(diǎn),所有任何不在棧頂?shù)脑囟紵o(wú)法訪(fǎng)問(wèn),為了拿到棧底的元素,必選先拿掉上面的元素

可在線(xiàn)演示這段代碼的執(zhí)行流程

function fun1(){
      return "hello hip-hop";
    }

    function fun2(){
      return fun1();
    }

    function fun3(){
      console.log(fun2());
    }

    fun3();   //"hello hip-hop"
                        
            
堆(引用類(lèi)型)
當(dāng)我們?cè)诔绦蛑袆?chuàng)建一個(gè)對(duì)象時(shí),這個(gè)對(duì)象將被保存到運(yùn)行時(shí)數(shù)據(jù)區(qū)中,以便反復(fù)利用(因?yàn)閷?duì)象的創(chuàng)建成本開(kāi)銷(xiāo)較大),這個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū)就是堆內(nèi)存。
堆內(nèi)存中的對(duì)象不會(huì)隨方法的結(jié)束而銷(xiāo)毀,即使方法結(jié)束后,這個(gè)對(duì)象還可能被另一個(gè)引用變量所引用(方法的參數(shù)傳遞時(shí)很常見(jiàn)),則這個(gè)對(duì)象依然不會(huì)被銷(xiāo)毀,只有當(dāng)一個(gè)對(duì)象沒(méi)有任何引用變量引用它時(shí),
系統(tǒng)的垃圾回收機(jī)制才會(huì)在核實(shí)的時(shí)候回收它對(duì)象被分配在一個(gè)堆中,即用以表示一個(gè)大部分非結(jié)構(gòu)化的內(nèi)存區(qū)域

隊(duì)列
排隊(duì)在第一個(gè)的人先辦理業(yè)務(wù),其它人只能排著,直到輪到他們?yōu)橹怪荒茉谀┪膊迦朐?,在?duì)首刪除元素。
隊(duì)列用于存儲(chǔ)按順序排列的數(shù)據(jù)先進(jìn)先出列被用在很多地方。比如提交操作系統(tǒng)執(zhí)行一系列進(jìn)程。打印任務(wù)池等。一些仿真系統(tǒng)用來(lái)模擬銀行或雜貨店里排隊(duì)的顧客
事件循環(huán)機(jī)制

這幅圖片中,我們可以看到完整的執(zhí)行流程,其中涉及到的異步事件有DOM事件、ajax請(qǐng)求和setTimeout。所以,整體的執(zhí)行流程是這樣子的:

所有同步任務(wù)會(huì)在主線(xiàn)程的調(diào)用棧中執(zhí)行。

在主線(xiàn)程之外,還有一個(gè)任務(wù)隊(duì)列,一旦指定事件發(fā)生之后,異步任務(wù)就會(huì)被放入任務(wù)隊(duì)列中

當(dāng)主線(xiàn)程執(zhí)行完調(diào)用棧中的同步任務(wù)時(shí),會(huì)遍歷任務(wù)隊(duì)列,將任務(wù)隊(duì)列中的任務(wù)放入主線(xiàn)程中執(zhí)行。而之后事件循環(huán)一直會(huì)去遍歷任務(wù)隊(duì)列,一旦有任務(wù)放入就會(huì)放入主線(xiàn)程中執(zhí)行。

這樣,我們就已經(jīng)初步了解了同步和異步之間的實(shí)現(xiàn),以及瀏覽器中的事件循環(huán)機(jī)制。

任務(wù)隊(duì)列
所謂任務(wù)是WebAPIs返回的一個(gè)個(gè)通知,讓JS主線(xiàn)程在讀取任務(wù)隊(duì)列的時(shí)候得知這個(gè)異步任務(wù)已經(jīng)完成,下一步該執(zhí)行這個(gè)任務(wù)的回調(diào)函數(shù)了。

主線(xiàn)程擁有多個(gè)任務(wù)隊(duì)列,不同的任務(wù)隊(duì)列用來(lái)排列來(lái)自不同任務(wù)源的任務(wù)。
任務(wù)源是什么?像setTimeout/Promise/DOM事件等都是任務(wù)源,來(lái)自同類(lèi)任務(wù)源的任務(wù)我們稱(chēng)它們是同源的,比如setTimeout與setInterval就是同源的
在ES6標(biāo)準(zhǔn)中任務(wù)隊(duì)列又分為宏觀(guān)任務(wù)隊(duì)列和微觀(guān)任務(wù)隊(duì)列

宏觀(guān)與微觀(guān)任務(wù)隊(duì)列
ES6標(biāo)準(zhǔn)中任務(wù)隊(duì)列存在兩種類(lèi)型,一種就是上邊提到的一些隊(duì)列,
宏觀(guān)任務(wù)隊(duì)列(macrotask queue):setTimeout、網(wǎng)絡(luò)請(qǐng)求Ajax、用戶(hù)IO等
微觀(guān)任務(wù)隊(duì)列(microtask queue),Promise就屬于微觀(guān)任務(wù)隊(duì)列
在執(zhí)行棧執(zhí)行的過(guò)程中會(huì)把屬于微觀(guān)任務(wù)隊(duì)列的任務(wù)分配到相應(yīng)的微觀(guān)任務(wù)隊(duì)列中去。而在調(diào)用棧執(zhí)行空之后,主線(xiàn)程讀取任務(wù)隊(duì)列時(shí),會(huì)先讀取所有微觀(guān)任務(wù)隊(duì)列,然后讀取一個(gè)宏觀(guān)任務(wù)隊(duì)列,再讀取所有的微觀(guān)任務(wù)隊(duì)列


setTimeout(function(){console.log(4)},0);
new Promise(function(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);

腳本開(kāi)始執(zhí)行,最先遇到setTimeout,交給瀏覽器去計(jì)時(shí),達(dá)到setTimeout限制最短計(jì)時(shí)之后,把這個(gè)任務(wù)推入setTimeout隊(duì)列。

遇到Promise構(gòu)造函數(shù),構(gòu)造函數(shù)參數(shù)執(zhí)行,輸出1,調(diào)用resolve改變Promise對(duì)象的狀態(tài),然后輸出2。
Promise對(duì)象調(diào)用then方法,將這個(gè)任務(wù)推入Promise任務(wù)隊(duì)列。
執(zhí)行console.log(3),輸出3。

調(diào)用棧為空,讀取任務(wù)隊(duì)列,按照 讀取所有微觀(guān)任務(wù)隊(duì)列 -> 執(zhí)行 ->

讀取一個(gè)宏觀(guān)任務(wù)隊(duì)列 -> 執(zhí)行 ->

讀取所有微觀(guān)任務(wù)隊(duì)列 -> 執(zhí)行 ->

再讀取一個(gè)宏觀(guān)任務(wù)隊(duì)列…的順序。

讀取所有微觀(guān)任務(wù)隊(duì)列中的任務(wù),執(zhí)行這些任務(wù)指定的回調(diào)函數(shù)。執(zhí)行then指定的回調(diào)函數(shù),輸出5(微觀(guān)任務(wù)隊(duì)列也具有優(yōu)先級(jí))。

最后讀取到setTimeout的任務(wù),執(zhí)行回調(diào)函數(shù),輸出4。

所以最后的輸出順序是1,2,3,5,4,而不是1,2,3,4,5。如果不清楚微觀(guān)任務(wù)隊(duì)列的執(zhí)行機(jī)制,很容易將兩個(gè)異步任務(wù)歸為一類(lèi),將執(zhí)行順序判斷錯(cuò)誤

零延遲
零延遲并不是意味著回調(diào)會(huì)立即執(zhí)行。 在零延遲調(diào)用 setTimeout 時(shí),其并不是過(guò)了給定的時(shí)間間隔后就馬上執(zhí)行回調(diào)函數(shù)。
其等待的時(shí)間基于隊(duì)列里正在等待的消息數(shù)量。 在下面的例子中,"this is just a message" 將會(huì)在回調(diào)
(callback) 獲得處理之前輸出到控制臺(tái), 這是因?yàn)檠舆t是要求運(yùn)行時(shí) (runtime) 處理請(qǐng)求所需的最小時(shí)間,但不是有所保證的時(shí)間
(function () {

  console.log("this is the start");

  setTimeout(function cb() {
    console.log("this is a msg from call back");
  });

  console.log("this is just a message");

  setTimeout(function cb1() {
    console.log("this is a msg from call back1");
  }, 0);

  console.log("this is the  end");

})();

// "this is the start"
// "this is just a message"
// "this is the end"
// "this is a msg from call back"
// "this is a msg from call back1"

參考
《javascript高級(jí)程序設(shè)計(jì)》
https://developer.mozilla.org...
http://www.cnblogs.com/ahthw/...
https://kongchenglc.github.io...
https://github.com/laizimo/zi...

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

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

相關(guān)文章

  • 那些年,前端學(xué)習(xí)之路的疑難雜癥(四):面試中遇到的3個(gè)問(wèn)題概覽

    摘要:閉包能用來(lái)實(shí)現(xiàn)私有化和創(chuàng)建工廠(chǎng)函數(shù)等作用。關(guān)于閉包的常見(jiàn)面試題是這樣的寫(xiě)一個(gè)函數(shù),循環(huán)一個(gè)整數(shù)數(shù)組,延遲秒打印這個(gè)數(shù)組中每個(gè)元素的索引。 文章來(lái)源:http://mp.weixin.qq.com/s/vs0... 前言 在公眾號(hào)上看到了這篇文章,覺(jué)得很有用,有助于理解JS學(xué)習(xí)中的一些重點(diǎn)難點(diǎn)。決定把它整理下發(fā)布出來(lái)。該文章主要介紹了JS中的三個(gè)問(wèn)題。在以后的幾篇文章里,我會(huì)詳細(xì)介紹這三...

    gecko23 評(píng)論0 收藏0
  • JavaScript疑難雜癥系列-事件

    摘要:支持三個(gè)參數(shù)分別表示事件名稱(chēng),是否可以冒泡,是否阻止事件的默認(rèn)操作觸發(fā)參數(shù)表示事件對(duì)象,是方法返回的創(chuàng)建的對(duì)象監(jiān)聽(tīng)方法自定義事件常用模擬模擬方法操作或者自定義事件我的自定義事件。 事件這塊知識(shí)點(diǎn)雖然是老生長(zhǎng)談的,但對(duì)于我來(lái)說(shuō)多多整理,多多感悟,溫故知新,每次看看這塊都有不同的收獲.(在這里我不會(huì)長(zhǎng)篇大論,只會(huì)挑重點(diǎn);具體的小伙伴們自行查找) 什么是事件 在編程時(shí)系統(tǒng)內(nèi)發(fā)生的動(dòng)作或者發(fā)生...

    CocoaChina 評(píng)論0 收藏0
  • JavaScript疑難雜癥系列-事件

    摘要:支持三個(gè)參數(shù)分別表示事件名稱(chēng),是否可以冒泡,是否阻止事件的默認(rèn)操作觸發(fā)參數(shù)表示事件對(duì)象,是方法返回的創(chuàng)建的對(duì)象監(jiān)聽(tīng)方法自定義事件常用模擬模擬方法操作或者自定義事件我的自定義事件。 事件這塊知識(shí)點(diǎn)雖然是老生長(zhǎng)談的,但對(duì)于我來(lái)說(shuō)多多整理,多多感悟,溫故知新,每次看看這塊都有不同的收獲.(在這里我不會(huì)長(zhǎng)篇大論,只會(huì)挑重點(diǎn);具體的小伙伴們自行查找) 什么是事件 在編程時(shí)系統(tǒng)內(nèi)發(fā)生的動(dòng)作或者發(fā)生...

    Anleb 評(píng)論0 收藏0
  • JavaScript疑難雜癥系列-事件

    摘要:支持三個(gè)參數(shù)分別表示事件名稱(chēng),是否可以冒泡,是否阻止事件的默認(rèn)操作觸發(fā)參數(shù)表示事件對(duì)象,是方法返回的創(chuàng)建的對(duì)象監(jiān)聽(tīng)方法自定義事件常用模擬模擬方法操作或者自定義事件我的自定義事件。 事件這塊知識(shí)點(diǎn)雖然是老生長(zhǎng)談的,但對(duì)于我來(lái)說(shuō)多多整理,多多感悟,溫故知新,每次看看這塊都有不同的收獲.(在這里我不會(huì)長(zhǎng)篇大論,只會(huì)挑重點(diǎn);具體的小伙伴們自行查找) 什么是事件 在編程時(shí)系統(tǒng)內(nèi)發(fā)生的動(dòng)作或者發(fā)生...

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

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

0條評(píng)論

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