最佳化 JavaScript 執行作業

JavaScript 經常會觸發視覺變更。有時候,您必須直接操控樣式,有時計算的計算結果會產生視覺上的變化,例如搜尋或排序資料。JavaScript 運作時間不正確或執行時間過長,是造成效能問題的常見原因。建議您盡可能減少影響。

Paul Lewis

JavaScript 經常會觸發視覺變更。有時 可能的計算結果 導致資料出現變動 例如搜尋或排序資料適中 或長時間執行的 JavaScript 是造成效能問題的常見原因。 建議您盡可能減少影響。

JavaScript 效能分析是藝術的一環,因為您編寫的 JavaScript 是 不會像實際執行的程式碼一樣新型瀏覽器會使用 JIT 編譯器, 會給你滿滿的最佳化和技巧,然後以最快的速度執行。 大幅改變程式碼的動態性

儘管如此,您還是可以採取幾項措施,讓應用程式順利執行 JavaScript。

摘要

  • 避免使用 setTimeout 或 setInterval 進行視覺更新;請一律改用 requestAnimationFrame。
  • 將長時間執行的 JavaScript 從主執行緒移至 Web Worker。
  • 使用微任務,對多個頁框進行 DOM 變更。
  • 使用 Chrome 開發人員工具的時間軸和 JavaScript 分析器評估 JavaScript 的影響。

使用 requestAnimationFrame 進行視覺變更

畫面出現視覺變化時,您想要讓工作適時發生 它就在影格開始處唯一能夠確保 JavaScript 程式碼的方法 會在影格啟動時執行,是使用 requestAnimationFrame

/**
    * If run as a requestAnimationFrame callback, this
    * will be run at the start of the frame.
    */
function updateScreen(time) {
    // Make visual updates here.
}

requestAnimationFrame(updateScreen);

架構或範例可以使用 setTimeoutsetInterval 進行視覺變更,例如動畫、 但這個問題的問題在於回呼會在影格的「某個時間點」執行,這個情況可能為 結尾,這通常會導致我們錯過影格,進而導致卡頓。

setTimeout 會導致瀏覽器錯過影格。

事實上,jQuery 會使用 setTimeout 執行 animate 行為。已變更為改用 requestAnimationFrame。 如果您使用的是舊版 jQuery 呼叫函式以使用 requestAnimationFrame, 這點是強烈建議的做法

降低複雜性或使用 Web Worker

JavaScript 會在瀏覽器的主執行緒上執行,旁邊則是計算樣式、版面配置和 繪製效果長時間執行 JavaScript 時,會阻止這些工作 所以可能漏掉影格

您必須戰略 JavaScript 的執行時間和時間長度。舉例來說,如果您在 最好是將 JavaScript 移到 區域是 3-4 毫秒。超過這個時間時,您可能花太多時間。如果你處於閒置狀態 就能夠讓您更放鬆地專注於完成時間。

在許多情況下,您可以將純運算工作 網路工作人員, 例如它不需要 DOM 存取權資料操縱或週遊 就像排序或搜尋一樣,通常很適合這個模型,因為載入和模型產生一樣。

var dataSortWorker = new Worker("sort-worker.js");
dataSortWorker.postMesssage(dataToSort);

// The main thread is now free to continue working on other things...

dataSortWorker.addEventListener('message', function(evt) {
    var sortedData = evt.data;
    // Update data on screen...
});

並非所有工作都符合這個模型:網路工作處理人員沒有 DOM 存取權。如果工作必須在主執行緒上,請考慮採用批次處理方法,將大型工作區隔為微任務,每項任務花費的時間都不超過數毫秒,並在各影格的 requestAnimationFrame 處理常式中執行。

這種做法會對使用者體驗和 UI 造成不良影響,因此您必須確保使用者知悉 透過進度或活動指標設定正在處理中的工作。 無論如何,這個做法都能讓應用程式的主執行緒保持釋放,讓應用程式能夠保持回應 使用者互動狀況

瞭解 JavaScript 的「影格稅金」

評估架構、程式庫或自有程式碼時,請務必評估 在每個影格上執行 JavaScript 程式碼需要多少費用。這是 尤其在執行攸關成效的動畫時尤其重要 播放或捲動

Chrome 開發人員工具的「效能」面板 JavaScript 的費用。通常您會取得如下的低層級記錄:

Chrome 開發人員工具中的效能記錄

「Main」區段提供 JavaScript 呼叫的火焰圖,方便您 可準確分析呼叫的函式和各呼叫所需的時間。

掌握這些資訊後,您就能評估 才能找出並修正 函式執行的時間太長。如先前所述,您應該 移除長時間執行的 JavaScript;如果行不通,則將其移動 就能讓主執行緒繼續處理其他工作。

如要瞭解如何使用分析執行階段效能,請參閱開始使用分析執行階段效能 「Performance」(效能) 面板。

避免對 JavaScript 進行微幅最佳化

也許您會知道 瀏覽器可以 100 倍的速度執行 100 倍 比如說,要求元素的 offsetTop 比運算速度更快 getBoundingClientRect(),但基本上只有在呼叫下列函式時才會呼叫函式: 其實每個影格只有少數幾次,通常沒辦法專心處理 JavaScript 的成效。通常只要幾毫秒就能儲存分數。

如果您開發的是遊戲,或運算耗用大量資源的應用程式,可能就屬於例外狀況 這是因為請注意,一個影格通常會包含大量運算資料,而且 確保一切都有幫助

簡而言之,微最佳化作業通常不會對應至 來建構應用程式