zoukankan      html  css  js  c++  java
  • 前端倒计时不准的问题


    电商网站,团购类网站很多都有都有秒杀这个业务。秒杀自然涉及前端倒计时的问题。前端倒计时许考虑两个问题:

    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种,笔者实验的过程中会有点问题。

  • 相关阅读:
    [在Windows上使用Unix工具]MKS
    [MySQL]导入导出
    《Excel与VBA程序设计》写作计划
    由Google Map API想开去
    《Excel与VBA程序设计》第七章
    转载:东拉西扯:产业链
    Google ToolBar 3.0 Beta试用
    UI和界面可用性设计
    《Excel与VBA程序设计》第一章
    关于通过COM自动化调用Excel的效率问题
  • 原文地址:https://www.cnblogs.com/xiaochongchong/p/5982004.html
Copyright © 2011-2022 走看看