前端倒計時不准的問題



電商網站,團購類網站很多都有都有秒殺這個業務。秒殺自然涉及前端倒計時的問題。前端倒計時許考慮兩個問題:

1.由於js是單線程的,也就是阻塞的,定時可定會不准。無論setTimeout()還是setInterval(),都有問題;

2、打開瀏覽器,然后切換到其他app,再次回到瀏覽器,這期間js可能停止執行的問題。

本質上來說,只需要兩個時間點就可以了:當前時間、秒殺開始時間。有了這兩個數據,我們就可以倒計時了。兩個時間的差值就是我們要倒計時的時間差,每隔1秒減少1/每隔1毫秒減少1。但是,當前的時間不要用new Date(),這是獲取手機的時間,如果用戶修改手機的時間,這個會跟隨變化的。基於此,當前的時間必須是服務端傳過來的。用戶每次打開網頁,都會傳服務器的當前時間。秒殺開始的時間一般是后台配置好的,只要配置了,他就定了。是個不變的量。

解決方法1

  以服務器的當前時間為倒計時的當前時間,上面提到需要考慮的那兩個問題都沒有解決,如果我們實時同步服務器的當前時間,那么這兩個問題就都解決了。
如何時時同步呢?最先想到的是,時時調用一個后端的接口,這個接口返回服務器的當前時間。但實際上,我們只需要跟服務器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

  還有種解決的辦法,就是計算每次倒計時的誤差,你能知道第n次你倒計時的應該發生的時間,再跟當前的時間對比,這個誤差就在下次倒計時的時候考慮進去。這樣可以保證誤差不累計。但是對於退出瀏覽器的行為,這種其實是有問題的。
這種方法是不斷校准倒計時的周期,而周期不可能為負數,治標不治本。
詳細代碼參考:http://www.cnblogs.com/flash3d/archive/2014/05/08/3715600.html

 

2種方法,第1種更好,不會有任何問題。而第2種,筆者實驗的過程中會有點問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM