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

資訊專欄INFORMATION COLUMN

event loop 與 vue

Barry_Ng / 620人閱讀

摘要:但是導(dǎo)致了很明顯的性能問題。上述兩個(gè)例子其實(shí)是在這個(gè)中找到的,第一個(gè)使用的版本是,這個(gè)版本的實(shí)現(xiàn)是采用了,而后因?yàn)榈睦锏挠?,于是尤雨溪更改了?shí)現(xiàn),換成了,也就是后一個(gè)所使用的。后來尤雨溪了解到是將回調(diào)放入的隊(duì)列。

結(jié)論

對(duì)于event loop 可以抽象成一段簡(jiǎn)單的代碼表示

for (macroTask of macroTaskQueue) {
    // 1. Handle current MACRO-TASK
    handleMacroTask();
      
    // 2. Handle all MICRO-TASK
    for (microTask of microTaskQueue) {
        handleMicroTask(microTask);
    }
}
js事件機(jī)制

javascript是一個(gè)單線程語言,同一時(shí)間只能執(zhí)行一個(gè)任務(wù)。
對(duì)于javascript的事件處理機(jī)制,我們可以簡(jiǎn)單理解成“主線程+任務(wù)隊(duì)列”模式。主要步驟如下

(1)所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧。

(2)主線程之外,還存在一個(gè) "任務(wù)隊(duì)列"(task queue)。只要異步任務(wù)有了運(yùn)行結(jié)果,就在 "任務(wù)隊(duì)列" 之中放置一個(gè)事件。
(3)一旦 "執(zhí)行棧" 中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會(huì)讀取 "任務(wù)隊(duì)列",看看里面有哪些事件。那些對(duì)應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。

(4)主線程不斷重復(fù)上面的第三步。

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

任務(wù)隊(duì)列分為task queue和microtask queue。執(zhí)行棧任務(wù)清空后會(huì)先從Microtasks中取任務(wù),Microtasks中執(zhí)行完之后才會(huì)執(zhí)行task中的任務(wù)。

因此一個(gè)event loop主要流程如下:

開始一個(gè)Event loop

執(zhí)行棧從tasks queue中取任務(wù),并執(zhí)行。

執(zhí)行完后,執(zhí)行棧清空

執(zhí)行棧從microtasks queue中取任務(wù)執(zhí)行

執(zhí)行完成,執(zhí)行棧清空

判斷microtasks queue是否還有任務(wù),有則重復(fù)步驟3。

進(jìn)入 Update the rendering(更新渲染)階段

Event loop結(jié)束

流程圖如下:

再仔細(xì)理解一下開頭列出的代碼:

for (macroTask of macroTaskQueue) {
    // 1. Handle current MACRO-TASK
    handleMacroTask();
      
    // 2. Handle all MICRO-TASK
    for (microTask of microTaskQueue) {
        handleMicroTask(microTask);
    }
}
VUE與EVENT_LOOP 為什么使用Microtask queue

對(duì)于VUE這類web2.0框架而言,最主要做的應(yīng)該還是把對(duì)data的修改映射到DOM上。如果只修改一個(gè)數(shù)據(jù),就刷新一次DOM,那么在一個(gè)同步過程中,同時(shí)修改好幾個(gè)數(shù)據(jù),必然會(huì)導(dǎo)致多次渲染。這肯定是不可取的。
從上面的event loop我們了解到,一個(gè)event loop對(duì)應(yīng)一次render。理想狀況當(dāng)然就是,一次event loop產(chǎn)生的所有改動(dòng)最好再render之前將DOM都先更新好。這樣在一個(gè)周期中就可以只render一次。

從這點(diǎn)需求出發(fā)很容易發(fā)現(xiàn),microtask queue很符合要求。

microtask queue肯定在render ui之前執(zhí)行完

不像task queue存在多個(gè),microtask只存在一個(gè)queue。

最關(guān)鍵的是: microtask queue只有都清空了才能進(jìn)入下一步,無論queue里是什么時(shí)候塞進(jìn)來的。

實(shí)際代碼中,不管是鼠標(biāo)點(diǎn)擊還是鍵盤輸入或是網(wǎng)絡(luò)時(shí)間,觸發(fā)了哪些方法,這些觸發(fā)都可以看成開啟一個(gè)event loop。這些觸發(fā)造成的任何修改都放到microtask queue中,就可以保證在這一輪的evnet loop走到render ui時(shí)可以拿到最新的DOM。

要說明的是,這里的render并不是維護(hù)虛擬DOM,也不是把虛擬DOM的變化投射到真實(shí)DOM上。而是將真實(shí)DOM更新到UI的過程。

這么說是因?yàn)椋篍vent Loop 并不是在 ECMAScript 標(biāo)準(zhǔn)中定義的,而是在 HTML 標(biāo)準(zhǔn)中定義的:

To coordinate events, user interaction, scripts, rendering, networking, and so forth...

在 JavaScript Engine 中(以 V8 為例),只是實(shí)現(xiàn)了 ECMAScript 標(biāo)準(zhǔn),而并不關(guān)心什么 Event Loop。也就是說 Event Loop 是屬于 JavaScript Runtime 的,是由宿主環(huán)境提供的(比如瀏覽器)。
瀏覽器可不會(huì)關(guān)心什么虛擬DOM。只負(fù)責(zé)DOM改變后渲染UI。

為什么不用task queue

同上: 在開啟一個(gè)event loop后,如果將任務(wù)放到task queue中,那么這個(gè)task任務(wù)只會(huì)在本輪Event loop結(jié)束后才會(huì)執(zhí)行,并開啟新一輪event loop。這無疑會(huì)導(dǎo)致兩次render UI。
實(shí)際上,尤大為了修復(fù)一些bug,曾經(jīng)將VUE.nexttick用task queue實(shí)現(xiàn)。但是導(dǎo)致了很明顯的性能問題。
可以看看兩個(gè)列子: 例一 , 例二
兩個(gè)fiddle的實(shí)現(xiàn)一模一樣,就是讓那個(gè)絕對(duì)定位的黃色元素起到一個(gè)fixed定位的效果:綁定scroll事件,每次滾動(dòng)的時(shí)候,計(jì)算當(dāng)前滾動(dòng)的位置并更改到那個(gè)絕對(duì)定位元素的top屬性上去。大家自己試試滾動(dòng)幾下,對(duì)比下效果,你就會(huì)發(fā)現(xiàn)第一個(gè)fiddle中的黃元素是穩(wěn)定不動(dòng)的,fixed很好。而后一個(gè)fiddle中就有問題了,黃色元素上下晃動(dòng),似乎跟不上我們scroll的節(jié)奏,總要慢一點(diǎn),雖然最后停下滾動(dòng)時(shí)位置是對(duì)的。

上述兩個(gè)例子其實(shí)是在這個(gè)issue中找到的,第一個(gè)jsfiddle使用的版本是Vue 2.0.0-rc.6,這個(gè)版本的nextTick實(shí)現(xiàn)是采用了MO,而后因?yàn)镮OS9.3的WebView里的MO有bug,于是尤雨溪更改了實(shí)現(xiàn),換成了window.postMessage,也就是后一個(gè)fiddle所使用的Vue 2.0.0-rc.7。后來尤雨溪了解到window.postMessage是將回調(diào)放入的macrotask 隊(duì)列。這就是問題的根源了。

參考:

Tasks, microtasks, queues and schedules

深入理解 JavaScript Event Loop

Vue源碼詳解之nextTick:MutationObserver只是浮云,microtask才是核心!

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

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

相關(guān)文章

  • event loop vue

    摘要:但是導(dǎo)致了很明顯的性能問題。上述兩個(gè)例子其實(shí)是在這個(gè)中找到的,第一個(gè)使用的版本是,這個(gè)版本的實(shí)現(xiàn)是采用了,而后因?yàn)榈睦锏挠校谑怯扔晗牧藢?shí)現(xiàn),換成了,也就是后一個(gè)所使用的。后來尤雨溪了解到是將回調(diào)放入的隊(duì)列。 結(jié)論 對(duì)于event loop 可以抽象成一段簡(jiǎn)單的代碼表示 for (macroTask of macroTaskQueue) { // 1. Handle cur...

    springDevBird 評(píng)論0 收藏0
  • JavaScript Event Loop 機(jī)制詳解 Vue.js 中實(shí)踐應(yīng)用

    摘要:機(jī)制詳解與中實(shí)踐應(yīng)用歸納于筆者的現(xiàn)代開發(fā)語法基礎(chǔ)與實(shí)踐技巧系列文章。事件循環(huán)機(jī)制詳解與實(shí)踐應(yīng)用是典型的單線程單并發(fā)語言,即表示在同一時(shí)間片內(nèi)其只能執(zhí)行單個(gè)任務(wù)或者部分代碼片。 JavaScript Event Loop 機(jī)制詳解與 Vue.js 中實(shí)踐應(yīng)用歸納于筆者的現(xiàn)代 JavaScript 開發(fā):語法基礎(chǔ)與實(shí)踐技巧系列文章。本文依次介紹了函數(shù)調(diào)用棧、MacroTask 與 Micr...

    livem 評(píng)論0 收藏0
  • Vue源碼詳解之nextTick:MutationObserver只是浮云,microtask才是核

    摘要:后來尤雨溪了解到是將回調(diào)放入的隊(duì)列。而且瀏覽器內(nèi)部為了更快的響應(yīng)用戶,內(nèi)部可能是有多個(gè)的而的的優(yōu)先級(jí)可能更高,因此對(duì)于尤雨溪采用的,甚至可能已經(jīng)多次執(zhí)行了的,都沒有執(zhí)行的,也就導(dǎo)致了我們更新操 原發(fā)于我的博客。 前一篇文章已經(jīng)詳細(xì)記述了Vue的核心執(zhí)行過程。相當(dāng)于已經(jīng)搞定了主線劇情。后續(xù)的文章都會(huì)對(duì)其中沒有介紹的細(xì)節(jié)進(jìn)行展開。 現(xiàn)在我們就來講講其他支線任務(wù):nextTick和micro...

    陳偉 評(píng)論0 收藏0
  • 優(yōu)秀文章收藏(慢慢消化)持續(xù)更新~

    摘要:整理收藏一些優(yōu)秀的文章及大佬博客留著慢慢學(xué)習(xí)原文協(xié)作規(guī)范中文技術(shù)文檔協(xié)作規(guī)范阮一峰編程風(fēng)格凹凸實(shí)驗(yàn)室前端代碼規(guī)范風(fēng)格指南這一次,徹底弄懂執(zhí)行機(jī)制一次弄懂徹底解決此類面試問題瀏覽器與的事件循環(huán)有何區(qū)別筆試題事件循環(huán)機(jī)制異步編程理解的異步 better-learning 整理收藏一些優(yōu)秀的文章及大佬博客留著慢慢學(xué)習(xí) 原文:https://www.ahwgs.cn/youxiuwenzhan...

    JeOam 評(píng)論0 收藏0
  • 初探 event loop

    摘要:事件循環(huán)了解知識(shí)點(diǎn)線程執(zhí)行棧線程是單線程的語言可以單線程將理解為只有一條車道在車道里后面的車在等前面的車通過后才能通過即當(dāng)前面的程序沒有執(zhí)行后面的程序也不能執(zhí)行執(zhí)行棧執(zhí)行棧像車道被執(zhí)行的程序會(huì)放入執(zhí)行棧里但它的執(zhí)行的順序是后面進(jìn)來的程序先執(zhí) 事件循環(huán) 了解知識(shí)點(diǎn) 線程 執(zhí)行棧 task queue web api macro task micro task 線程 javascrip...

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

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

0條評(píng)論

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