電商網站,團購類網站不少都有都有秒殺這個業務。秒殺天然涉及前端倒計時的問題。前端倒計時許考慮兩個問題:javascript
1.因爲js是單線程的,也就是阻塞的,定時可定會不許。不管setTimeout()仍是setInterval(),都有問題;html
二、打開瀏覽器,而後切換到其餘app,再次回到瀏覽器,這期間js可能中止執行的問題。前端
本質上來講,只須要兩個時間點就能夠了:當前時間、秒殺開始時間。有了這兩個數據,咱們就能夠倒計時了。兩個時間的差值就是咱們要倒計時的時間差,每隔1秒減小1/每隔1毫秒減小1。可是,當前的時間不要用new Date(),這是獲取手機的時間,若是用戶修改手機的時間,這個會跟隨變化的。基於此,當前的時間必須是服務端傳過來的。用戶每次打開網頁,都會傳服務器的當前時間。秒殺開始的時間通常是後臺配置好的,只要配置了,他就定了。是個不變的量。java
解決方法1:ajax
以服務器的當前時間爲倒計時的當前時間,上面提到須要考慮的那兩個問題都沒有解決,若是咱們實時同步服務器的當前時間,那麼這兩個問題就都解決了。
如什麼時候時同步呢?最早想到的是,時時調用一個後端的接口,這個接口返回服務器的當前時間。但實際上,咱們只須要跟服務器ajax交互就能夠了,請求一個服務器不存在的資源,咱們從返回中拿返回頭,再從這個頭中取服務器的當前時間。
這種方法就是不斷的同步服務器的事件。
詳細代碼參考:https://www.zhihu.com/question/28896402
https://zhuanlan.zhihu.com/p/20832837?refer=xiaojue後端
筆者的代碼:瀏覽器
var this_start_time//指定秒殺開始的時間點,服務器傳過來的 var this_count_down;//時間差:指定秒殺開始時間減去當前時間。能夠先不初始化。 //校準倒計時的秒數函數 function sync(){ var xhr = new XMLHttpRequest(); xhr.open('get', '/', true); xhr.onreadystatechange = function() { if (xhr.readyState === 3) { var now = xhr.getResponseHeader('Date'); var nowTime = new Date(now).valueOf()/1000;//沒有毫秒值,咱們倒計時的最小單位是秒。有毫秒,不除以1000 this_count_down =this_start_time - nowTime; xhr.abort(); } }; xhr.send(null); } //先對this_count_down初始化 sync(); if(this_count_down>0){ setInterval(function(){ sync(); this_count_down--; },1000) }else{ alert('倒計時結束 ') }
以上代碼的欠缺是每次請求服務器,性能不佳。但好處也顯而易見,3個用戶同時訪問頁面,他們的倒計時結果基本上同樣的,秒殺變得比較公平。當服務器出現問題,請求不到服務器的當前時間,這個代碼會有問題,但這不是咱們考慮的問題。服務器
解決方法2:app
還有種解決的辦法,就是計算每次倒計時的偏差,你能知道第n次你倒計時的應該發生的時間,再跟當前的時間對比,這個偏差就在下次倒計時的時候考慮進去。這樣能夠保證偏差不累計。可是對於退出瀏覽器的行爲,這種實際上是有問題的。
這種方法是不斷校準倒計時的週期,而週期不可能爲負數,治標不治本。
詳細代碼參考:http://www.cnblogs.com/flash3d/archive/2014/05/08/3715600.html函數
2種方法,第1種更好,不會有任何問題。而第2種,筆者實驗的過程當中會有點問題。