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