關於倒計時的一些探討
最近項目中有應用到倒計時,其中出現了一些問題和問題的解決方案,覺得蠻有分享價值,於是決定寫篇文章記錄一下。
主要問題:如何保證倒計時以服務器時間為准?
這是很普遍的問題,雖然后端可以做校驗,但是難免本地時間會和服務器時間存在偏差,導致用戶體驗並不友好。(明明本地時間已經是倒計時結束了,可是還是無法正常展示該展示的功能)
對於這個問題,我們該選用setTimeout
+循環的形式還是setInterval
。個人認為還是使用setInterval
更加符合我們的業務邏輯。
方案1:每次倒計時去服務端請求時間
code:
var myInterval = setInterval(function(){
//執行請求 獲取當前服務端時間 並進行相應操作
},1000)
這個方案對於稍微有點經驗的開發人員來說,都知道是不可取的。因為這會給服務器造成無法想象的壓力,導致應用崩潰。比如我在這個頁面停留一分鍾,那么請求就發送了60次,假如此時有100個人在訪問這個頁面,那么一分鍾就有6000條請求,人數如果再增長,這絕對會造成不必要的服務器壓力。並且這個方案的倒計時,也會存在很大的誤差,因為請求存在延遲,跟你的網絡狀態也有很大的關系。
方案2:從服務端返回以服務器時間為基准的倒計時時間戳
code:
//假設請求獲取到一個時間戳 TIMEDIFF
var myInterval = setInterval(function(){
TIMEDIFF--;
//執行頁面倒計時的渲染
},1000)
優點:
- 一個頁面只請求一次
- 本地修改時間也無法更改倒計時
缺點:
- js自帶的計時器並不是百分百准確依據所指定的時間,進行定時工作,影響其准確度的情況有很多,假如頁面一直打開,那么與實際的偏差量會越來越大。
改進版
//假設請求獲取到一個時間戳 TIMEDIFF
var endTime = Date.now()+TIMEDIFF;//以本地時間為基准獲得一個結束時間
var myInterval = setInterval(function(){
var countDown = endTime - Date.now()
//每秒會獲取本地時間,這樣就算執行的周期不准確
//也可以准確的獲取時間差
//執行頁面倒計時的渲染
},1000)
方案3:入口js請求接口獲取本地時間與服務器時間的差值
//entry.js入口文件
...
if(!window.dateDiff){
$.get('api/GetTimeDiff',
{nowDate:Date.now()},
function(dateDiff){
window.dateDiff = dateDiff;
//講時間差存在全局變量中,方便在其他模塊中調用
})
}
...
//other.js 其他模塊
...
var myInterval = setInterval(function(){
var countDown = endTime - Date.now()+dateDiff;
//每秒會獲取本地時間,這樣就算執行的周期不准確
//也可以准確的獲取時間差
//執行頁面倒計時的渲染
},1000)
...
優點:
- 入口文件獲取請求,使該請求只在頁面生命周期中請求一次
- 准確度高,就算頁面打開很久還是保持高准確度
缺點:
- 由於每秒獲取當前時間,假如有人刻意在倒計時時期內,修改了時間將會導致倒計時異常。
總結
當然,解決方案肯定不只以上幾種,歡迎有想法的同學補充。對比以上三個方案,第一個不可行,第二和第三本質上是類似的東西,只是第三種方案將差值從模塊中抽離出來,並且調用次數也降低了很多,個人會比較喜歡第三種方案。此文章會持續保持更新狀態,有想法,有問題的同學都可以聯系我!!
引:http://www.cnblogs.com/cydiacen/p/6287538.html