Javascript实现商品秒杀倒计时(时间与服务器时间同步)


Posted in Javascript onSeptember 16, 2015

现在有很多网站都在做秒杀商品,而这其中有一个很重要的环节就是倒计时。

关于倒计时,有下面几点需要注意:

1.应该使用服务器时间而不是本地时间(本地时间存在时区不同、用户自行设置等问题)。

2.要考虑网络传输的耗时。

3.获取时间时可直接从AJAX的响应头中读取(通过getResponseHeader('Date')来获得),服务器端不需要专门写时间生成脚本。

过程分析:

1.从服务器读到一个时间戳之后便开始计时,不考虑网络传输的耗时:

Javascript实现商品秒杀倒计时(时间与服务器时间同步)

图中的各项标注分别是(上面的时间线采用标准时间,与服务器和页面的时间均无关):

start——页面项服务器发起AJAX请求时的时间。

www_start——服务器响应页面的请求并返回时间戳给页面的时间。

pc_start——页面接受到服务器返回的时间戳并开始计时的时间。

www_end——服务器倒计时结束的时间。

pc_end——页面倒计时结束的时间,同时也是用户在倒计时结束那一刻点击按钮的时间。

end——服务器接收到用户点击信息的时间。

可以看出,即使在倒计时结束的那一刻(也就是秒杀开始那一刻)用户就立即点击鼠标,也会比实际开始抢拍的时间(www_end,即服务器倒计时结束的时间)晚一些(可以很容易的看出,这个时间差正好等于pc_start - start,也就是AJAX从开始发送到接收到响应信息的耗时)。如果有些内行在页面倒计时结束前用脚本发送请求,那么其他用户可就亏大了。所以,我们要解决掉这个时间误差的问题。

2.为了解决时间误差的问题,我们将把页面倒计时的时间缩短一小截(由上面的分析可以得出,这一小截正好等于pc_start - start),使得用户在倒计时结束时发送给服务器的抢拍信息正好在服务器倒计时结束时被接收到:

Javascript实现商品秒杀倒计时(时间与服务器时间同步)

图中的各项标注与Pic.1中相同(时间线采用标准时间,与服务器和页面的时间均无关),新增的两项标注的含义如下:

old_pc_end——在未对网络传输耗时进行处理的情况下pc_end的时间。

old_end——在未对网络传输耗时进行处理的情况下end的时间。

由Pic.2可见,网络传输耗时造成的时间误差已经完全被弥补了,弥补的方法是“将倒计时结束的时间提前pc_start - start”。但是解决了网络传输耗时造成的误差问题,还有用户电脑时间和服务器时间不相同的问题,下面我们继续讨论。

3.用户的电脑时间和服务器时间一定是有差异的,甚至差几个时区,怎么解决这个问题呢?方法的要点如下:

A. 当页面接收到服务器返回的时间戳www_t时,立即开始计时。

B. 当页面接收到服务器返回的时间戳www_t时,立即计算本地时间和服务器返回的时间戳的时间差t=new Date().getTime() - www_t*1000。

C. 仍然使用new Date().getTime()来计时,而不是使用setInterval()函数(计时器很不稳定,误差也很大),但时间的显示与程序的逻辑必须基于本地时间和上一步(B中)求得的时间偏差t。

结论要点:

页面从接收到服务器响应的时间戳开始计时,计时的时长应减掉AJAX从发送到接收整个过程的耗时,计时过程则使用本地时间来实现(本地时间+时间偏差)。

有任何疑问或建议请留言,谢谢!

javascript小技巧:同步服务器时间、同步倒计时

之前在网上看到有人提问,如何在页面上同步显示服务器的时间,其实实现方法有几种,可能一般人立马就想到可以使用Ajax每隔一秒去请求服务器,然后将服务器获取到时间显示在页面上,这样虽然能够实现,但存在一个很大的问题,那就是每隔一秒去请求服务器,这样如果用户多了,服务器就会崩溃(内存占用率会很大),所以在我看来,这种方法不可行,我这里给出一种解决方案,能够实现同步服务器时间、同步倒计时,却不占用服务器太多资源,下面我给写实现的思路

第一步,当用户第一次浏览页面时,服务器首先获取当前时间并显示在页面上(比如:显示在ID为timebox span中)

第二步,设置一个每隔一秒就计算新的时间(新时间以服务器时间为初始值,然后每隔一秒累加一秒并生成新的时间)

第三步,显示第二步计算的时间

是不是很简单,总结成一句话就是:以服务器时间为初始值,然后在页面上自动每隔一秒就累加一秒生成新时间,这样就能保证与服务器时间同步了,误差基本在几秒内,应该没关系了,好了看一下实现的代码吧:

<span id="timebox">11:21:55</span> //第一次将服务器时间显示在这里
<script type="text/javascript">
  $(function () {
    var oTime = $("#timebox");
    var ts = oTime.text().split(":", 3);
    var tnums = [parseInt(ts[0]), parseInt(ts[1]), parseInt(ts[2])];
    setInterval(function () {
      tnums = getNextTimeNumber(tnums[0], tnums[1], tnums[2]);
      showNewTime(tnums[0], tnums[1], tnums[2]);
    }, 1000);
    function showNewTime(h, m, s) {
      var timeStr = ("0" + h.toString()).substr(-2) + ":"
              + ("0" + m.toString()).substr(-2) + ":"
              + ("0" + s.toString()).substr(-2);
      oTime.text(timeStr);
    }
    function getNextTimeNumber(h, m, s) {
      if (++s == 60) {
        s = 0;
      }
      if (s == 0) {
        if (++m == 60) {
          m = 0;
        }
      }
      if (m == 0) {
        if (++h == 24) {
          h = 0;
        }
      }
      return [h, m, s];
    }
  });
</script>

代码很简单在此就不多作说明(我上面只显示时分秒,大家也可以加上日期,加上日期可在当h==0时,直接从服务器获取一个日期或完整的时间,作为一次时间的校对),不懂的可以在下面评论,我会及时回复的,然后按照这种思路来实现一下同步倒计时,首先说明一下,什么是同步倒计时,就是类似秒杀一样,设置一个结束时间,然后计算当前时间与结束时间之间间隔,而且必需保证在不同的电脑、浏览器上显示的倒计时时间均相同,实现代码如下:

<!DOCTYPE html>
<html>
<head>
  <title>同步倒计时</title>
  <script type="text/javascript" src="jquery-1.4.4.min.js"></script>
</head>
<body>
  <span id="timebox">1天00时00分12秒</span> <!--假设:1天00时00分12秒是从服务器获取的倒计时数据-->
  <script type="text/javascript">
    $(function () {
      var tid = setInterval(function () {
        var oTimebox = $("#timebox");
        var syTime = oTimebox.text();
        var totalSec = getTotalSecond(syTime) - 1;
        if (totalSec >= 0) {
          oTimebox.text(getNewSyTime(totalSec));
        } else {
          clearInterval(tid);
        }
 
      }, 1000);
 
      //根据剩余时间字符串计算出总秒数
      function getTotalSecond(timestr) {
        var reg = /\d+/g;
        var timenums = new Array();
        while ((r = reg.exec(timestr)) != null) {
          timenums.push(parseInt(r));
        }
        var second = 0, i = 0;
        if (timenums.length == 4) {
          second += timenums[0] * 24 * 3600;
          i = 1;
        }
        second += timenums[i] * 3600 + timenums[++i] * 60 + timenums[++i];
        return second;
      }
 
      //根据剩余秒数生成时间格式
      function getNewSyTime(sec) {
        var s = sec % 60;
        sec = (sec - s) / 60; //min
        var m = sec % 60;
        sec = (sec - m) / 60; //hour
        var h = sec % 24;
        var d = (sec - h) / 24;//day
        var syTimeStr = "";
        if (d > 0) {
          syTimeStr += d.toString() + "天";
        }
 
        syTimeStr += ("0" + h.toString()).substr(-2) + "时"
              + ("0" + m.toString()).substr(-2) + "分"
              + ("0" + s.toString()).substr(-2) + "秒";
 
        return syTimeStr;
      }
 
    });
  </script>
</body>
</html>

为了保证倒计时的精确度,我采用了先将倒计时时间间隔统一计算成秒,然后减1秒再重新生成时间格式,当然也可以按照上面时间同步的例子,直接进行时间减少,方法很多,我这个不一定是最优的,欢迎大家交流,谢谢!

Javascript 相关文章推荐
js中将多个语句写成一个语句的两种方法小结
Dec 08 Javascript
js下用eval生成JSON对象
Sep 17 Javascript
JavaScript函数定义的常见注意事项小结
Sep 16 Javascript
JavaScript获取页面上被选中文字的方法技巧
Mar 13 Javascript
jQuery插件slick实现响应式移动端幻灯片图片切换特效
Apr 12 Javascript
JavaScript禁止微信浏览器下拉回弹效果
May 16 Javascript
深入解析Vue 组件命名那些事
Jul 18 Javascript
layui实现点击按钮给table添加一行
Aug 10 Javascript
基于vue中keep-alive缓存问题的解决方法
Sep 21 Javascript
JavaScript基于遍历操作实现对象深拷贝功能示例
Mar 05 Javascript
如何优雅地在vue中添加权限控制示例详解
Mar 07 Javascript
浅谈Node 异步IO和事件循环
May 05 Javascript
JS+CSS实现的经典tab选项卡效果代码
Sep 16 #Javascript
使用JavaScript脚本无法直接改变Asp.net中Checkbox控件的Enable属性的解决方法
Sep 16 #Javascript
jQuery实现的超酷苹果风格图标滑出菜单效果代码
Sep 16 #Javascript
jQuery实现的简单折叠菜单(折叠面板)效果代码
Sep 16 #Javascript
JS实现不规则TAB选项卡效果代码
Sep 16 #Javascript
JQuery通过AJAX从后台获取信息显示在表格上并支持行选中
Sep 15 #Javascript
jQuery实现图片轮播特效代码分享
Sep 15 #Javascript
You might like
索尼SONY SRF-S83/84电路分析和打磨
2021/03/02 无线电
php zend解密软件绿色版测试可用
2008/04/14 PHP
Yii PHP Framework实用入门教程(详细介绍)
2013/06/18 PHP
PHP 微信支付类 demo
2015/11/30 PHP
Windows上php5.6操作mongodb数据库示例【配置、连接、获取实例】
2019/02/13 PHP
基于jquery的3d效果实现代码
2011/03/23 Javascript
JS截取字符串常用方法整理及使用示例
2013/10/18 Javascript
javascript事件冒泡详解和捕获、阻止方法
2014/04/12 Javascript
js实现两点之间画线的方法
2015/05/12 Javascript
如何判断出一个js对象是否一个dom对象
2016/11/24 Javascript
Bootstrap 响应式实用工具实例详解
2017/03/29 Javascript
Vue中如何实现轮播图的示例代码
2017/07/27 Javascript
纯JS实现的读取excel文件内容功能示例【支持所有浏览器】
2018/06/23 Javascript
基于vue实现移动端圆形旋钮插件效果
2018/11/28 Javascript
vue插件draggable实现拖拽移动图片顺序
2018/12/01 Javascript
layui字体图标 loading图标静止不旋转的解决方法
2019/09/23 Javascript
Django中实现一个高性能计数器(Counter)实例
2014/07/09 Python
利用Python中的mock库对Python代码进行模拟测试
2015/04/16 Python
Python实现的数据结构与算法之双端队列详解
2015/04/22 Python
python 实现网上商城,转账,存取款等功能的信用卡系统
2016/07/15 Python
详解python3中tkinter知识点
2018/06/21 Python
python dlib人脸识别代码实例
2019/04/04 Python
Kali Linux安装ipython2 和 ipython3的方法
2019/07/11 Python
在python中用print()输出多个格式化参数的方法
2019/07/16 Python
python3实现网页版raspberry pi(树莓派)小车控制
2020/02/12 Python
解决Python Matplotlib绘图数据点位置错乱问题
2020/05/16 Python
Pycharm配置lua编译环境过程图解
2020/11/28 Python
顶级宝石首饰网络零售商:Angara
2016/10/25 全球购物
旅游管理实习自我鉴定
2013/09/29 职场文书
大学生毕业的自我评价分享
2014/01/02 职场文书
幼儿园秋游感想
2014/03/12 职场文书
关于运动会的广播稿
2015/08/19 职场文书
2016年小学生寒假家长评语
2015/10/10 职场文书
市直属机关2016年主题党日活动总结
2016/04/05 职场文书
Python包管理工具pip的15 个使用小技巧
2021/05/17 Python
《LOL》“克隆大作战”久违归来 幻灵战队皮肤上线
2022/04/03 其他游戏