JavaScript >> Javascript 文檔 >  >> JavaScript

使用 setImmediate 產生的腳本

參加過我關於 JavaScript 性能演講的人都熟悉我使用 setTimeout() 的傾向 將長腳本分解成更小的塊。使用 setTimeout() 時 ,您正在更改某些代碼的執行時間,從而有效地讓 UI 線程執行已排隊的任務。例如,您可以通過以下方式指示一些代碼在 50ms 後添加到 UI 線程隊列中:

setTimeout(function(){

   //do  something

}, 50)

所以在 50ms 之後,這個函數被添加到隊列中,並在輪到它時立即執行。對 setTimeout() 的調用 有效地讓當前的 JavaScript 任務完成,從而可以進行下一次 UI 更新。

問題

儘管我一直非常支持使用 setTimeout() 通過這種方式,這種技術存在一些問題。首先,跨瀏覽器的計時器分辨率各不相同。 Internet Explorer 8 及更早版本的計時器分辨率為 15.6 毫秒,而 Internet Explorer 9 及更高版本以及 Chrome 的計時器分辨率為 4 毫秒。所有瀏覽器都強制執行 setTimeout() 的最小延遲 ,所以 setTimeout(fn, 0) 實際是0ms後執行,是定時器解析後執行。

另一個問題是電源使用。管理計時器會耗盡筆記本電腦和移動設備的電池。 Chrome 曾嘗試將計時器分辨率降低到 1 毫秒,然後才發現它會損害筆記本電腦的電池壽命。最終,決定回到 4 毫秒的計時器分辨率。此後,其他瀏覽器也紛紛效仿,儘管許多後台選項卡的節流計時器分辨率為 1 秒。微軟發現將定時器分辨率降低到 1ms 可以將電池運行時間減少 25%。事實上,Internet Explorer 9 在筆記本電腦使用電池運行時將計時器分辨率保持在 15.6 毫秒,而在插入電源時僅增加到 4 毫秒。

setImmediate() 函數

W3C Web 性能工作組的 Efficient Script Yielding 規範定義了一個新函數來實現這種腳本分解,稱為 setImmediate() . setImmediate() function 接受單個參數,該參數是要執行的函數,它會插入該函數以在 UI 線程空閒時立即執行。基本用法:

var id = setImmediate(function(){

    //do something

});

setImmediate() 函數返回一個 ID,可用於通過 clearImmediate() 取消調用 如有必要。

也可以將參數傳遞到 setImmediate() 函數參數通過在末尾包含它們:

setImmediate(function(doc, win){

    //do something

}, document, window);

以這種方式傳遞附加參數意味著您不必總是使用帶有 setImmediate() 的閉包 以便為執行函數提供有用的信息。

優勢

什麼setImmediate() 確實使瀏覽器無需為此過程管理計時器。瀏覽器可以簡單地等待 UI 隊列清空,然後插入新的 JavaScript 任務,而不是等待系統中斷,這會消耗更多的電量。 Node.js 開發人員可能會從 process.nextTick() 開始識別此功能 在那種環境中做同樣的事情。

另一個優點是指定的函數在更短的延遲後執行,無需等待下一個計時器滴答聲。這意味著整個過程的完成速度比使用 setTimeout(fn, 0) 快得多 .

瀏覽器支持

目前,只有 Internet Explorer 10 支持 setImmediate() , 它通過 msSetIntermediate() 因為規範尚未最終確定。 Internet Explorer 10 Test Drive 站點有一個 setImmediate() 顯示使用新方法改進性能的示例。該示例使用延遲對值進行排序,同時直觀地顯示排序的當前狀態。此示例需要 Internet Explorer 10。

未來

我很看好setImmediate() 功能及其對 Web 開發人員的價值。使用計時器來生成腳本是一種 hack,當然,使用官方的方式來生成腳本對於性能來說是一個巨大的勝利。我希望其他瀏覽器能很快接受這個實現,這樣我們就可以盡快開始使用它了。


Tutorial JavaScript 教程
  1. JavaScript 對象鍵

  2. 使用 PixiJS 的簡單數學冒險遊戲

  3. 重複顯示數據

  4. 為什麼需要開始使用 Intersection Observer

  5. 為什麼我今天是 React、GraphQL 和 Firebase 的粉絲?

  6. 為什麼這個“else if”功能不能與 Google Appscript 上的 onEdit 一起使用?

  7. 使用 Fastify 對 Pino 的 TypeScript 支持

  1. 如何在郵遞員測試中將字符串與日期進行比較?

  2. 使用 Blazor JavaScript 互操作

  3. 如何編寫更好的 async/await + promise 代碼?

  4. 與 GitHub 的持續集成

  5. React 的動畫發現

  6. let 和 var 的區別

  7. 我如何建立自己的獎勵卡

  1. Javascript 樂趣(動作)!探索 3 種最熱門的數組方法:Map、Filter 和 Reduce

  2. React + TypeScript + ESLint + Prettier 完整設置✈

  3. 🎂 hapi pal v3:生日版

  4. 使用快速會話的最簡單的登錄應用程序