使用 isInputPending() 改善 JS 排程

提供新的 JavaScript API,協助您避免在載入效能與輸入回應之間權衡取捨。

Nate Schloss
Nate Schloss
Andrew Comminos
Andrew Comminos

快速載入很難,目前使用 JS 顯示內容的網站 必須在負載效能與輸入之間取得平衡 回應:執行所有必要的顯示工作 (提高載入效能、降低輸入回應速度),或 將工作分割成較小的任務,以便快速回應 輸入和繪製 (降低負載效能,輸入更佳) 回應)。

為了省去做出這項取捨,Facebook 建議和實施 Chromium 中的 isInputPending() API,以便在沒有提示的情況下提升回應速度 。我們已根據來源試用意見回饋,對 API;好消息是,Chromium 已預設採用這個 API 87!

瀏覽器相容性

瀏覽器支援

  • Chrome:87。
  • Edge:87。
  • Firefox:不支援。
  • Safari:不支援。

資料來源

自 87 版起,isInputPending() 已在以 Chromium 為基礎的瀏覽器中推出。 沒有其他瀏覽器發出傳送 API 的意圖。

背景

當今 JS 生態系統中的多數工作,都是在單一執行緒上完成:主執行緒。 這可為開發人員提供健全的執行模型,但使用者體驗。 (尤其是回應能力) 如果指令碼長時間執行,可能會大幅改善 讓應用程式從可以最快做出回應的位置 回應使用者要求如果網頁在觸發輸入事件時執行大量工作, 舉例來說,網頁要等到作業完成後,才會處理點擊輸入事件 完成。

如要處理此問題,目前的最佳做法就是將 將 JavaScript 轉換為較小的區塊網頁載入時,網頁可以執行 然後產生控制項,再將控制項傳回瀏覽器。 瀏覽器可以檢查輸入事件佇列,看看是否有任何 不需要告知網頁資訊接著瀏覽器就會改回使用 每次新增 JavaScript 模塊這雖然有幫助,但可能會造成其他問題。

每次網頁恢復到瀏覽器後,瀏覽器需要一些時間 檢查輸入事件佇列、處理事件,然後取得下一個 JavaScript 區塊瀏覽器能更快回應事件,但整體 進而減緩網頁載入時間如果結果顯示頻率過高 載入速度太慢。如果我們降低頻率,瀏覽器 回覆使用者事件,就會感到厭煩。無趣。

這張圖表顯示當您執行長時間的 JS 工作時,瀏覽器在傳送事件的時間會比較少。

在 Facebook,我們想瞭解如果 採用新的載入方式,以消除這方面的取捨。三 聯絡我們的 Chrome 朋友,提出這項提案 (isInputPending())。isInputPending() API 是第一個採用 導致 JavaScript 能夠檢查輸入,而不會傳回瀏覽器。

顯示 isInputPending() 的圖表可讓 JS 檢查是否有待處理的使用者輸入內容,而不會完全傳回瀏覽器執行作業。

因為對 API 感興趣,我們與 Chrome 的同事合作 實作並發布這項功能。讓 Chrome 助您一臂之力 都能在來源試用後試用修補程式 (Chrome 可以用這種方式測試變更,並取得開發人員的意見回饋 再全面發布 API)。

我們已從來源試用和其他團隊成員收集意見回饋, W3C Web Performance Working Group 並且實作了 API 變更。

範例:收益器排程器

假設 例如從元件產生標記、分解質數或 繪製一個很酷的載入旋轉圖示每項參數都分成多個獨立版本 工作項目。我們來看看排程器模式,接著大致說明 我們在假想的 processWorkQueue() 函式中執行工作:

const DEADLINE = performance.now() + QUANTUM;
while (workQueue.length > 0) {
  if (performance.now() >= DEADLINE) {
    // Yield the event loop if we're out of time.
    setTimeout(processWorkQueue);
    return;
  }
  let job = workQueue.shift();
  job.execute();
}

我們稍後會透過 setTimeout() 在新的巨集工作中叫用 processWorkQueue() 讓瀏覽器保持輸入的靈敏度 (可 執行事件處理常式),同時仍設法讓整個工作繼續進行 不受廣告幹擾。不過,我們可能對其他工作安排很長的時間 想要控制事件迴圈,或最多額外等待 QUANTUM 毫秒 事件延遲的狀況。

好吧,但我們可以做得更好嗎?沒錯!

const DEADLINE = performance.now() + QUANTUM;
while (workQueue.length > 0) {
  if (navigator.scheduling.isInputPending() || performance.now() >= DEADLINE) {
    // Yield if we have to handle an input event, or we're out of time.
    setTimeout(processWorkQueue);
    return;
  }
  let job = workQueue.shift();
  job.execute();
}

加入對 navigator.scheduling.isInputPending() 的呼叫,讓我們能夠 加快回應輸入速度,同時確保 否則就會不中斷。如果我們沒有興趣處理任何事情 繪製內容 (例如繪畫) 才算完成,我們還可以手動增加 系統也要支援 QUANTUM 的長度。

根據預設,系統會設為「連續」。isInputPending() 不會傳回事件。這些 包括 mousemovepointermove 等。如果你想要為 這些指令也是一樣透過以下方式向 isInputPending() 提供物件: 已將 includeContinuous 設為 true,很好:

const DEADLINE = performance.now() + QUANTUM;
const options = { includeContinuous: true };
while (workQueue.length > 0) {
  if (navigator.scheduling.isInputPending(options) || performance.now() >= DEADLINE) {
    // Yield if we have to handle an input event (any of them!), or we're out of time.
    setTimeout(processWorkQueue);
    return;
  }
  let job = workQueue.shift();
  job.execute();
}

大功告成!React 等架構正在建構 isInputPending() 支援, 使用類似邏輯的核心排程程式庫希望這能 開發人員使用這些架構後,isInputPending() 然後並不費力改寫

收益不一定總是不佳

值得注意的是,獲取較少的資源不一定適合每次使用 確認是否屬於此情況有很多原因會讓瀏覽器恢復使用控制權,但 處理輸入事件,例如在 該網頁。

在某些情況下,瀏覽器無法正確判定待處理屬性 輸入事件尤其是為跨來源設定複雜的短片和遮罩 iframe 可能會回報偽陰性 (例如,isInputPending() 可能意外傳回) false)。請確定您的收益充足 你的網站需要與風格化子頁框互動

也請留意共用事件迴圈的其他網頁。在這類平台上 不同於 Android 版 Chrome,多個來源共用事件也很常見 迴圈如果輸入內容分派給isInputPending()true 所以背景頁面可能會幹擾 前景頁面的回應。建議減緩、延期或產出 使用 Page Visibility API 在背景執行時的頻率更高。

建議您斟酌使用 isInputPending()。如果沒有 持續實行使用者封鎖的作業,並善加利用事件迴圈中的其他人 因此更頻繁地顯示長時間的工作可能會有害

意見回饋

結論

我們很高興推出「isInputPending()」,讓開發人員能夠 立即開始使用這個 API 是 Facebook 首次建立 全新的 Web API 並將實驗從構思構想轉化為標準提案 運費感謝所有為我們提供協助的人員 並特別為大豐收的 Chrome 使用者致謝 並將想法寄給我們!

主頁橫幅:Will H McMahan Unsplash