摘要:因?yàn)榛卣{(diào)的執(zhí)行的前提條件是當(dāng)前瀏覽器處于空閑狀態(tài)。除了不推薦修改操作外,的操作也不建議放在里面,因?yàn)榈幕卣{(diào)會(huì)在的回調(diào)執(zhí)行完成后立刻執(zhí)行,會(huì)拉長(zhǎng)當(dāng)前幀的耗時(shí),所以不推薦。推薦放在里面的應(yīng)該是小塊的并且可預(yù)測(cè)時(shí)間的任務(wù)。
我們都知道React 16實(shí)現(xiàn)了新的調(diào)度策略(Fiber), 新的調(diào)度策略提到的異步、可中斷,其實(shí)就是基于瀏覽器的 requestIdleCallback和requestAnimationFrame兩個(gè)API。所以這里我們有必要了解一下這兩個(gè)API,關(guān)于Fiber部分后面會(huì)單開幾篇講。
什么是requestIdleCallback?當(dāng)關(guān)注用戶體驗(yàn),不希望因?yàn)橐恍┎恢匾娜蝿?wù)(如統(tǒng)計(jì)上報(bào))導(dǎo)致用戶感覺到卡頓的話,就應(yīng)該考慮使用requestIdleCallback。因?yàn)閞equestIdleCallback回調(diào)的執(zhí)行的前提條件是當(dāng)前瀏覽器處于空閑狀態(tài)。
requestIdleCallback will schedule work when there is free time at the end of a frame, or when the user is inactive.
requestIdleCallback用法示例
requestIdelCallback(myNonEssentialWork); function myNonEssentialWork (deadline) { // deadline.timeRemaining()可以獲取到當(dāng)前幀剩余時(shí)間 while (deadline.timeRemaining() > 0 && tasks.length > 0) { doWorkIfNeeded(); } if (tasks.length > 0){ requestIdleCallback(myNonEssentialWork); } }requestIdleCallback和requestAnimationFrame有什么區(qū)別?
requestAnimationFrame的回調(diào)會(huì)在每一幀確定執(zhí)行,屬于高優(yōu)先級(jí)任務(wù),而requestIdleCallback的回調(diào)則不一定,屬于低優(yōu)先級(jí)任務(wù)。
我們所看到的網(wǎng)頁,都是瀏覽器一幀一幀繪制出來的,通常認(rèn)為FPS為60的時(shí)候是比較流暢的,而FPS為個(gè)位數(shù)的時(shí)候就屬于用戶可以感知到的卡頓了,那么在一幀里面瀏覽器都要做哪些事情呢,如下所示:
圖中一幀包含了用戶的交互、js的執(zhí)行、以及requestAnimationFrame的調(diào)用,布局計(jì)算以及頁面的重繪等工作。
假如某一幀里面要執(zhí)行的任務(wù)不多,在不到16ms(1000/60)的時(shí)間內(nèi)就完成了上述任務(wù)的話,那么這一幀就會(huì)有一定的空閑時(shí)間,這段時(shí)間就恰好可以用來執(zhí)行requestIdleCallback的回調(diào),如下圖所示:
由于requestIdleCallback利用的是幀的空閑時(shí)間,所以就有可能出現(xiàn)瀏覽器一直處于繁忙狀態(tài),導(dǎo)致回調(diào)一直無法執(zhí)行,這其實(shí)也并不是我們期望的結(jié)果(如上報(bào)丟失),那么這種情況我們就需要在調(diào)用requestIdleCallback的時(shí)候傳入第二個(gè)配置參數(shù)timeout了?
requestIdleCallback(myNonEssentialWork, { timeout: 2000 }); function myNonEssentialWork (deadline) { // 當(dāng)回調(diào)函數(shù)是由于超時(shí)才得以執(zhí)行的話,deadline.didTimeout為true while ((deadline.timeRemaining() > 0 || deadline.didTimeout) && tasks.length > 0) { doWorkIfNeeded(); } if (tasks.length > 0) { requestIdleCallback(myNonEssentialWork); } }
如果是因?yàn)閠imeout回調(diào)才得以執(zhí)行的話,其實(shí)用戶就有可能會(huì)感覺到卡頓了,因?yàn)橐粠膱?zhí)行時(shí)間必然已經(jīng)超過16ms了
requestIdleCallback里面可以執(zhí)行DOM修改操作嗎?強(qiáng)烈建議不要,從上面一幀的構(gòu)成里面可以看到,requestIdleCallback回調(diào)的執(zhí)行說明前面的工作(包括樣式變更以及布局計(jì)算)都已完成。如果我們?cè)赾allback里面做DOM修改的話,之前所做的布局計(jì)算都會(huì)失效,而且如果下一幀里有獲取布局(如getBoundingClientRect、clientWidth)等操作的話,瀏覽器就不得不執(zhí)行強(qiáng)制重排工作,這會(huì)極大的影響性能,另外由于修改dom操作的時(shí)間是不可預(yù)測(cè)的,因此很容易超出當(dāng)前幀空閑時(shí)間的閾值,故而不推薦這么做。推薦的做法是在requestAnimationFrame里面做dom的修改,可以在requestIdleCallback里面構(gòu)建Document Fragment,然后在下一幀的requestAnimationFrame里面應(yīng)用Fragment。
除了不推薦DOM修改操作外,Promise的resolve(reject)操作也不建議放在里面,因?yàn)镻romise的回調(diào)會(huì)在idle的回調(diào)執(zhí)行完成后立刻執(zhí)行,會(huì)拉長(zhǎng)當(dāng)前幀的耗時(shí),所以不推薦。
推薦放在requestIdleCallback里面的應(yīng)該是小塊的(microTask)并且可預(yù)測(cè)時(shí)間的任務(wù)。關(guān)于microTask推薦看這里
requestIdleCallback的兼容情況
推薦使用npm包request-idle-callback
https://developers.google.com...
https://medium.com/@paul_iris...
https://juejin.im/entry/59082...
https://insights.thoughtworks...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/94379.html
摘要:我將這個(gè)策略稱之為閑置直到緊急。請(qǐng)注意,在腳本執(zhí)行時(shí),它作為單個(gè)任務(wù)需要毫秒才能運(yùn)行完成。很明顯,解決方案是將這些代碼分解為多個(gè)任務(wù)。原因如下推遲組件初始化僅在組件尚未渲染時(shí)才有用。這稱為輸入優(yōu)先級(jí)。 showImg(https://img.alicdn.com/tfs/TB1u.rsepzqK1RjSZFzXXXjrpXa-1919-913.png); Idle Until Urge...
摘要:在上面我們已經(jīng)知道瀏覽器是一幀一幀執(zhí)行的,在兩個(gè)執(zhí)行幀之間,主線程通常會(huì)有一小段空閑時(shí)間,可以在這個(gè)空閑期調(diào)用空閑期回調(diào),執(zhí)行一些任務(wù)。另外由于這些堆棧是可以自己控制的,所以可以加入并發(fā)或者錯(cuò)誤邊界等功能。 文章首發(fā)于個(gè)人博客 前言 2016 年都已經(jīng)透露出來的概念,這都 9102 年了,我才開始寫 Fiber 的文章,表示慚愧呀。不過現(xiàn)在好的是關(guān)于 Fiber 的資料已經(jīng)很豐富了,...
摘要:開始寫代碼構(gòu)造函數(shù)講了那么多的理論,大家一定是暈了,但是沒辦法,架構(gòu)已經(jīng)比之前的簡(jiǎn)單要復(fù)雜太多了,因此不可能指望一次性把的內(nèi)容全部理解,需要反復(fù)多看。 前言 Facebook 的研發(fā)能力真是驚人, Fiber 架構(gòu)給 React 帶來了新視野的同時(shí),將調(diào)度一詞介紹給了前端,然而這個(gè)架構(gòu)實(shí)在不好懂,比起以前的 Vdom 樹,新的 Fiber 樹就麻煩太多。 可以說,React 16 和 ...
摘要:架構(gòu)理解引用原文是核心算法正在進(jìn)行的重新實(shí)現(xiàn)。構(gòu)建的過程就是的過程,通過來調(diào)度執(zhí)行一組任務(wù),每完成一個(gè)任務(wù)后回來看看有沒有插隊(duì)的更緊急的,把時(shí)間控制權(quán)交還給主線程,直到下一次回調(diào)再繼續(xù)構(gòu)建。 React Fiber 架構(gòu)理解 引用原文:React Fiber ArchitectureReact Fiber is an ongoing reimplementation of Reacts...
摘要:圖離線情況下發(fā)送微信消息,等網(wǎng)絡(luò)正常后微信會(huì)繼續(xù)處理我們的消息。無論是在微信中還是手機(jī)短信,在沒有信號(hào)時(shí)都不影響我們編輯發(fā)送短信,等網(wǎng)絡(luò)恢復(fù)時(shí)會(huì)自動(dòng)幫我們把之前編輯好的信息順利遞送出去。 (刪掉了第一小段,因?yàn)楹蛢?nèi)容關(guān)系不大。。) 本來這該是個(gè)技術(shù)分享會(huì)的內(nèi)容,參加完 Google Developer Day(GDD) 后想做個(gè) AI Demo 來分享,奈何技術(shù)實(shí)力不夠,害怕把大家?guī)нM(jìn)...
閱讀 2594·2021-09-22 15:41
閱讀 1518·2021-08-19 10:54
閱讀 1854·2019-08-23 15:11
閱讀 3452·2019-08-23 10:23
閱讀 1499·2019-08-22 16:28
閱讀 851·2019-08-22 15:11
閱讀 787·2019-08-22 14:53
閱讀 771·2019-08-22 13:49