1. 程式人生 > >移動 Web 與 JavaScript 定時器

移動 Web 與 JavaScript 定時器

文章目錄

提醒:本文最後更新於 1700 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

在之前部落格中,我曾經寫過「PC 上的 Firefox、Chrome 和 Safari 等瀏覽器,都會自動把未啟用頁面中的 JavaScript 定時器(setTimeout、setInterval)間隔最小值改為 1 秒以上;而移動裝置上的瀏覽器往往會直接凍結未啟用頁面上的所有定時器」。今天繼續聊一聊 JavaScript 定時器與移動 Web 這個話題。

計時器

最簡單的計時器只需要一個時間變數和固定間隔執行的函式就可以了,定期把上一次時間(預設為系統初始時間)加上執行間隔就是當前時間了。在 PC 上,這樣實現的計時器只要執行間隔沒有小於 1s,多半沒什麼大問題。但移動端不一樣,只要頁面不在前臺顯示,計時器就徹底不走了。

這個問題很容易解決,只要把定時器函式裡的時間累加邏輯,換成每次都從系統時間獲取就可以了。那如果系統時間不準怎麼辦?實際上大部分智慧手機,預設都會開啟網路校時,而且很多人有拿手機當手表的習慣,所以移動 Web 裡獲取到的系統時間,相比 PC 端,要準確得多。

更嚴謹的做法是服務端輸出頁面時帶上伺服器時間,JS 計時器先算出這個時間與系統時間之差 Δt,之後每次都用當前系統時間 + Δt 來還原伺服器時間。邏輯很簡單不多介紹了,說兩個問題:

1)如果定時器執行時,使用者改了系統時間怎麼辦?這個問題有很多解決方案,但是在移動裝置上卻有個偷懶的辦法,由於移動裝置上修改系統時間幾乎一定會讓頁面進入後臺,所以我們只需要在頁面「從後臺切回」時重新整理下頁面就好了。

2)移動裝置在 2G 等網路環境下,接收響應需要更長時間,很有可能 JS 從頁面上拿到伺服器時間,已經是幾十秒之後的事情了,喪失了準確性。如果一定要解決這個問題,使用 HTML5 新增的 Navigation Timing API 來修正是一種思路。美中不足的是 Android 4.0+ 才支援,Safari 系列則從未支援過這個 API。

從後臺切回

要判斷移動端頁面是否從後臺切回有很多方案,但利用後臺頁面定時器被凍結這個特性,有個簡便且通用的做法:

var lastTime = +new Date;
setInterval(function() {
    if(Math.abs(+new
Date - lastTime) > 3000) { alert('從後臺切回!'); } lastTime = +new Date; }, 1000);

原理很簡單,每隔一段時間(如 1s)更新頁面上某個變數,如果下次這個變數與當前系統時間之差大於某個閾值(如 3s),說明頁面定時器肯定被凍結過,也就是說頁面是從後臺切回來。程式碼中加上 Math.abs 是因為使用者可能把系統時間往回改(當然極端情況下還是會檢測不出來,忽略就好了)。

另一種定時器

我曾寫過一篇「不會被 iOS 停掉的網頁定時器」,原理是利用不會被 iOS 凍結的 <meta> 標籤 refresh 功能模擬 JS 定時器,有興趣的同學可以點這裡瞭解下。

--EOF--

提醒:本文最後更新於 1700 天前,文中所描述的資訊可能已發生改變,請謹慎使用。