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 相关文章推荐
javascript JSON操作入门实例
Apr 16 Javascript
JavaScript数据结构与算法之栈与队列
Jan 29 Javascript
js获取当前年月日-YYYYmmDD格式的实现代码
Jun 01 Javascript
js利用clipboardData实现截屏粘贴功能
Oct 12 Javascript
微信小程序  生命周期详解
Oct 27 Javascript
使用Curl命令查看请求响应时间方法
Nov 04 Javascript
javascript prototype原型详解(比较基础)
Dec 26 Javascript
JavaScript字符串检索字符的方法
Jun 23 Javascript
基于JavaScript表单脚本(详解)
Oct 18 Javascript
一秒学会微信小程序制作table表格
Feb 14 Javascript
js实现消灭星星(web简易版)
Mar 24 Javascript
Vue中通过vue-router实现命名视图的问题
Apr 23 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/06/14 PHP
PHP 数组教程 定义数组
2009/10/23 PHP
使用PHPMailer发送邮件实例
2017/02/15 PHP
PHPstorm快捷键(分享)
2017/07/17 PHP
关于php支持的协议与封装协议总结(推荐)
2017/11/17 PHP
PHP PDOStatement::nextRowset讲解
2019/02/01 PHP
php简单计算权重的方法示例【适合抽奖类应用】
2019/06/10 PHP
理解Javascript_13_执行模型详解
2010/10/20 Javascript
jquery 文本上下无缝滚动,鼠标放上去就停止 小例子
2013/06/05 Javascript
JS 实现点击a标签的时候让其背景更换
2013/10/15 Javascript
javascript 循环调用示例介绍
2013/11/20 Javascript
js+HTML5实现canvas多种颜色渐变效果的方法
2015/06/05 Javascript
轻松实现javascript图片轮播特效
2016/01/13 Javascript
jQuery数据检索中根据关键字快速定位GridView指定行的实现方法
2016/06/08 Javascript
Boostrap实现的登录界面实例代码
2016/10/09 Javascript
AngularJS验证信息框架的封装插件用法【w5cValidator扩展插件】
2016/11/03 Javascript
react-native 圆弧拖动进度条实现的示例代码
2018/04/12 Javascript
不得不知的ES6小技巧
2018/07/28 Javascript
Nodejs封装类似express框架的路由实例详解
2020/01/05 NodeJs
解决React在安装antd之后出现的Can't resolve './locale'问题(推荐)
2020/05/03 Javascript
在Python中使用判断语句和循环的教程
2015/04/25 Python
详解Python Socket网络编程
2016/01/05 Python
Python后台开发Django会话控制的实现
2019/04/15 Python
python 计算平均平方误差(MSE)的实例
2019/06/29 Python
Opencv求取连通区域重心实例
2020/06/04 Python
Python 如何反方向迭代一个序列
2020/07/28 Python
python cookie反爬处理的实现
2020/11/01 Python
python实现猜拳游戏项目
2020/11/30 Python
The Body Shop美体小铺西班牙官网:天然化妆品
2019/06/21 全球购物
厨师长岗位职责范本
2014/08/25 职场文书
大学生上课迟到检讨书
2014/10/15 职场文书
领导干部考核评语
2015/01/04 职场文书
小学班主任工作经验交流材料
2015/11/02 职场文书
化工生产实习心得体会
2016/01/22 职场文书
Navicat连接MySQL错误描述分析
2021/06/02 MySQL
python如何利用traceback获取详细的异常信息
2021/06/05 Python