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 相关文章推荐
弹出窗口并且此窗口带有半透明的遮罩层效果
Mar 13 Javascript
DEDECMS如何为文章添加HOT NEW标志图片
Aug 14 Javascript
你不知道的高性能JAVASCRIPT
Jan 18 Javascript
对js中回调函数的一些看法
Aug 29 Javascript
JavaScript脚本语言是什么_动力节点Java学院整理
Jun 26 Javascript
vue-router 实现导航守卫(路由卫士)的实例代码
Sep 02 Javascript
vue+VeeValidate 校验范围实例详解(部分校验,全部校验)
Oct 19 Javascript
微信小程序常用赋值方法小结
Apr 30 Javascript
Vue CL3 配置路径别名详解
May 30 Javascript
jQuery 查找元素操作实例小结
Oct 02 jQuery
vue cli3 配置proxy代理无效的解决
Oct 30 Javascript
动态实现element ui的el-table某列数据不同样式的示例
Jan 22 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
PHP的开发框架的现状和展望
2007/03/16 PHP
PHP下用rmdir实现删除目录的三种方法小结
2008/04/20 PHP
php从数组中随机抽取一些元素的代码
2012/11/05 PHP
详解PHP安装mysql.so扩展的方法
2016/12/31 PHP
Laravel路由研究之domain解决多域名问题的方法示例
2019/04/04 PHP
Laravel 创建可以传递参数 Console服务的例子
2019/10/14 PHP
PHP使用JpGraph绘制折线图操作示例【附源码下载】
2019/10/18 PHP
菜单效果
2006/10/14 Javascript
jQuery实现图片放大预览实现原理及代码
2013/09/12 Javascript
JS实现点击图片在当前页面放大并可关闭的漂亮效果
2013/10/18 Javascript
jQuery事件用法详解
2016/10/06 Javascript
inner join 内联与left join 左联的实例代码
2017/09/18 Javascript
Angular2管道Pipe及自定义管道格式数据用法实例分析
2017/11/29 Javascript
Vue.use源码学习小结
2018/06/20 Javascript
mpvue中使用flyjs全局拦截的实现代码
2018/09/13 Javascript
JavaScript指定断点操作实例教程
2018/09/18 Javascript
微信公众号获取用户地理位置并列出附近的门店的示例代码
2019/07/25 Javascript
vue实现信息管理系统
2020/05/30 Javascript
python实现批量转换文件编码(批转换编码示例)
2014/01/23 Python
Python 冒泡,选择,插入排序使用实例
2015/02/05 Python
对DataFrame数据中的重复行,利用groupby累加合并的方法详解
2019/01/30 Python
Python根据成绩分析系统浅析
2019/02/11 Python
详解python程序中的多任务
2020/09/16 Python
Python+OpenCV图像处理—— 色彩空间转换
2020/10/22 Python
CSS3控制HTML元素动画效果
2014/02/08 HTML / CSS
CSS3实现swap交换动画
2016/01/19 HTML / CSS
HTML5拍照和摄像机功能实战详解
2019/01/24 HTML / CSS
Expedia西班牙:预订酒店、机票、旅行和廉价度假套餐
2019/04/10 全球购物
韩国商务邀请函
2014/01/14 职场文书
九年级物理教学反思
2014/01/29 职场文书
统计专业自荐书
2014/07/06 职场文书
安全责任书怎么写
2014/07/28 职场文书
2014年教育教学工作总结
2014/11/13 职场文书
浅谈如何保证Mysql主从一致
2022/03/13 MySQL
Python的代理类实现,控制访问和修改属性的权限你都了解吗
2022/03/21 Python
MySQL新手入门进阶语句汇总
2022/09/23 MySQL