你應當曉得的requestIdleCallback

我們都曉得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為個位數的時刻就屬於用戶能夠感知到的卡頓了,那末在一幀內里瀏覽器都要做哪些事變呢,以下所示:

《你應當曉得的requestIdleCallback》

圖中一幀包含了用戶的交互、js的實行、以及requestAnimationFrame的挪用,規劃盤算以及頁面的重繪等事情。
假如某一幀內里要實行的使命不多,在不到16ms(1000/60)的時候內就完成了上述使命的話,那末這一幀就會有肯定的餘暇時候,這段時候就正好能夠用來實行requestIdleCallback的回調,以下圖所示:

《你應當曉得的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的兼容狀況

《你應當曉得的requestIdleCallback》
引薦運用npm包request-idle-callback

參考資料

https://developers.google.com…
https://medium.com/@paul_iris…
https://juejin.im/entry/59082…
https://insights.thoughtworks…

    原文作者:Randal
    原文地址: https://segmentfault.com/a/1190000014457824
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞