為何你的 Interval 會越跑越慢?閒置狀態頁籤中的 setTimeout、setInterval 發生什麼事
瀏覽器為了避免閒置頁籤浪費資源的種種節流
❓ 前端用 setInterval 寫的時鐘,過一陣子回來越跑越慢了,為什麼?
在背景頁籤中執行的 Timer 會默默消耗莫大的資源,沒在使用的閒置頁籤甚至影響到正在使用的頁籤,為了避免不必要的資源浪費,瀏覽器會針對閒置狀態等頁籤的 Timer 做節流
在 Chrome 上,無論程式碼中設定的 Interval、Timeout 時間為多少,Chrome 都會強制設定為至少一秒。意指如果你原本程式中寫的是 setInterval() 每 50ms 執行一次,但只要進入其他頁籤,讓該頁籤進入背景時,該 Interval 執行時間會節流至 每 1000ms 執行一次,但是只要重新點回該頁籤,Timer 的節流又會取消
在 2021年1月 時,Chrome 88 以上的版本甚至在特定條件下,該節流時間會被拉長到 1分鐘
一些後面會提到的術語也先做基本講解:
-
隱藏頁籤
代表有其他頁籤現在是正在被可見的,也就是說使用者切換到其他頁籤,或是瀏覽器被縮到最小化。而瀏覽器的頁籤是能夠透過 Page visibility api 得知的
-
Timer
代表 Javascript 的 setTimeout
以及 setInterval
,可以透過 Timer 來安排未來要執行的事件
-
連鎖 Timer
代表 setTimeout 或 setInterval 是接連執行的,例如 每秒更新時鐘時間
💻 Chrome 節流條件?節流影響?
節流分階段性:
🔒 最小節流
只要滿足下述任何條件,就只會有最小程度的節流
- 網頁是可見的(非隱藏頁籤)
- 在過去 30秒 內,網頁有透過任何 發聲API 製造過聲音(無聲的音軌除外)
在這階段下基本上瀏覽器不會做任何節流,除非你的 Timer 的時間設定低於 4ms,且連鎖次數大於5次時,瀏覽器會將時間設定為至少 4ms
🔒 一般節流
這種情況發生於 你的 Timer 不滿足上述情況(意指你的頁籤不為可見狀態,且在過去30秒內頁籤也沒有製造做任何聲音),且任何下述條件成立滿足時:
- Timer 連鎖次數低於五次
- 頁籤處在隱藏狀態,但時間低於五分鐘
- 頁籤正在使用 WebRTC(網頁間實現音頻、數據通信的技術)
在這階段下,瀏覽器會節流至每 1秒 才執行一次。時間接近的 Timer 則會批次一起被進行
🔒 高強度的節流
這部分是 Chrome 88 開始才有的新內容,當你的 Timer 已經不滿足上述兩個節流階段(例如瀏覽器已經閒置至少五分鐘),且滿足以下所有條件時會發生:
- 頁籤已經處於隱藏狀態超過五分鐘
- Timer 連鎖數量超過五次
- 該頁籤已經至少30秒沒發過任何聲音
- 沒有使用 WebRTC
在這階段下,瀏覽器會節流至每 1分鐘 才執行一次
🔨 實測
在執行以下程式碼時,我預期每秒鐘會印一次當前時間
- 一開始會很正常的每秒印出時間
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- 但當頁籤處在隱藏狀態超過一分鐘後,瀏覽器開始節流,變為
每分鐘執行一次
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- 後面皆為每分鐘執行一次
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- 直到 上午 1:08:52 點回該頁籤,頁籤重新成為可見狀態,時間立刻變回一秒印一次
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
📌 Workarounds
-
Web workers
Web workers 是一種允許網頁在背景執行緒 運行的機制,且可以不阻塞主線程正常運行。從這篇文章所說,上述節流的機制僅會進行在瀏覽器的主執行緒上,所以透過讓 Timer 在 Web workers執行緒上運行則能避免被節流(能看此 Demo,利用 Web workers 的 Timer 與 沒有 在 Web workers 上運行的 Timer 差距會越來越大)
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
-
監聽頁籤狀態
如果為了避免瀏覽器的 Timer 被節流進而影響到網頁的話,可以在頁籤進入背景時,可以透過監聽原生 Web API 事件 visibilitychange,預先將相關 Timer 中斷
參考文獻: