js前端如何写一个精确的倒计时代码


Posted in Javascript onOctober 25, 2019

关于写倒计时大家可能都都比较熟悉,使用 setTimeout 或 setInterval 就可以搞定。几秒钟或者几分钟的倒计时这样写没有问题,但是如果是长时间的倒计时,这样写就会不准确。如果用户修改了他的设备时间,这样的倒计时就没有意义了。今天就说说写一个精确的倒计时的方法。

原理

众所周知 setTimeout 或者 setInterval 调用的时候会有微小的误差。有人做了一个 demo 来观察这个现象并对其做了修正。短时间的误差倒也可以接受,但是作为一个长时间的倒计时,误差累计就会导致倒计时不准确。

因此我们可以在获取剩余时间的时候,每次 new 一个设备时间,因为设备时间的流逝相对是准确的,并且如果设备打开了网络时间同步,也会解决这个问题。

但是,如果用户修改了设备时间,那么整个倒计时就没有意义了,用户只要将设备时间修改为倒计时的 endTime 就可以轻易看到倒计时结束是页面的变化。因此一开始获取服务端时间就是很重要的。

简单的说,一个简单的精确倒计时原理如下:

  • 初始化时请求一次服务器时间 serverTime,再 new 一个设备时间 deviceTime
  • deviceTime 与 serverTime 的差作为时间偏移修正
  • 每次递归时 new 一个系统时间,解决 setTimeout 不准确的问题

代码

获取剩余时间的代码如下:

/**
 * 获取剩余时间
 * @param {Number} endTime  截止时间
 * @param {Number} deviceTime 设备时间
 * @param {Number} serverTime 服务端时间
 * @return {Object}      剩余时间对象
 */
let getRemainTime = (endTime, deviceTime, serverTime) => {
  let t = endTime - Date.parse(new Date()) - serverTime + deviceTime
  let seconds = Math.floor((t / 1000) % 60)
  let minutes = Math.floor((t / 1000 / 60) % 60)
  let hours = Math.floor((t / (1000 * 60 * 60)) % 24)
  let days = Math.floor(t / (1000 * 60 * 60 * 24))
  return {
    'total': t,
    'days': days,
    'hours': hours,
    'minutes': minutes,
    'seconds': seconds
  }
}

获取服务器时间可以使用 mtop 接口 mtop.common.getTimestamp

然后可以通过下面的方式来使用:

// 获取服务端时间(获取服务端时间代码略)
getServerTime((serverTime) => {

  //设置定时器
  let intervalTimer = setInterval(() => {

    // 得到剩余时间
    let remainTime = getRemainTime(endTime, deviceTime, serverTime)

    // 倒计时到两个小时内
    if (remainTime.total <= 7200000 && remainTime.total > 0) {
      // do something

    //倒计时结束
    } else if (remainTime.total <= 0) {
      clearInterval(intervalTimer);
      // do something
    }
  }, 1000)
})

这样的的写法也可以做到准确倒计时,同时也比较简洁。不需要隔段时间再去同步一次服务端时间。

补充

在写倒计时的时候遇到了一个坑这里记录一下。

千万别在倒计时结束的时候请求接口。会让服务端瞬间 QPS 峰值达到非常高。

js前端如何写一个精确的倒计时代码

如果在倒计时结束的时候要使用新的数据渲染页面,正确的做法是:

在倒计时结束前的一段时间里,先请求好数据,倒计时结束后,再渲染页面。

关于倒计时,如果你有什么更好的解决方案,欢迎评论交流。

Javascript 相关文章推荐
jQuery chili图片远处放大插件
Nov 30 Javascript
JS打开层/关闭层/移动层动画效果的实例代码
May 11 Javascript
js脚本获取webform服务器控件的方法
May 16 Javascript
使用delegate方法为一个tr标签加一个链接
Jun 27 Javascript
javascript加减乘除的简单实例
Jul 12 Javascript
JavaScript关于提高网站性能的几点建议(一)
Jul 24 Javascript
vue-cli启动本地服务局域网不能访问的原因分析
Jan 22 Javascript
工作中常用到的ES6语法
Sep 04 Javascript
vue-cli项目使用mock数据的方法(借助express)
Apr 15 Javascript
bootstrap table插件动态加载表头
Jul 19 Javascript
关于JS模块化的知识点分享
Oct 16 Javascript
解决VUE项目localhost端口服务器拒绝连接,只能用127.0.0.1的问题
Aug 14 Javascript
对layui数据表格动态cols(字段)动态变化详解
Oct 25 #Javascript
layui实现数据表格隐藏列的示例
Oct 25 #Javascript
关于在LayUI中使用AJAX提交巨坑记录
Oct 25 #Javascript
浅谈layui 绑定form submit提交表单的注意事项
Oct 25 #Javascript
详解如何在Vue项目中发送jsonp请求
Oct 25 #Javascript
layui实现form表单同时提交数据和文件的代码
Oct 25 #Javascript
vue实现弹幕功能
Oct 25 #Javascript
You might like
php常用文件操作函数汇总
2014/11/22 PHP
thinkphp5 migrate数据库迁移工具
2018/02/20 PHP
Yii框架学习笔记之session与cookie简单操作示例
2019/04/30 PHP
使用CSS3实现字体颜色渐变的实现
2021/03/09 HTML / CSS
js实现弹出窗口、页面变成灰色并不可操作的例子分享
2014/05/10 Javascript
jquery实现兼容IE8的异步上传文件
2015/06/15 Javascript
使用jQuery判断浏览器滚动条位置的方法
2016/05/30 Javascript
Bootstrap实现弹性搜索框
2016/07/11 Javascript
jQuery+HTML5+CSS3制作支持响应式布局时间轴插件
2016/08/10 Javascript
BootStrapValidator初使用教程详解
2017/02/10 Javascript
JavaScript实现短暂提示框功能
2018/04/04 Javascript
原生js封装的ajax方法示例
2018/08/02 Javascript
解决layui 表单元素radio不显示渲染的问题
2019/09/04 Javascript
VUE实现图片验证码功能
2020/11/18 Javascript
详解python如何调用C/C++底层库与互相传值
2016/08/10 Python
python+matplotlib绘制简单的海豚(顶点和节点的操作)
2018/01/02 Python
python中利用zfill方法自动给数字前面补0
2018/04/10 Python
Python实现的维尼吉亚密码算法示例
2018/04/12 Python
Python3.5 Pandas模块之DataFrame用法实例分析
2019/04/23 Python
简单了解python的break、continue、pass
2019/07/08 Python
使用Python绘制台风轨迹图的示例代码
2020/09/21 Python
python实现企业微信定时发送文本消息的示例代码
2020/11/24 Python
基于CSS3实现的漂亮Menu菜单效果代码
2015/09/10 HTML / CSS
工作的心得体会
2013/12/31 职场文书
《会变的花树叶》教学反思
2014/02/10 职场文书
导游个人求职信
2014/04/25 职场文书
英语专业毕业生求职信
2014/05/24 职场文书
大型演出策划方案
2014/05/28 职场文书
2014年教师政治学习材料
2014/06/02 职场文书
先进事迹材料范文
2014/12/29 职场文书
办公经费申请报告
2015/05/15 职场文书
2015年社区国庆节活动总结
2015/07/30 职场文书
职业规划从高考志愿专业选择开始
2019/08/08 职场文书
springboot如何初始化执行sql语句
2021/06/22 Java/Android
Nginx本地配置SSL访问的实例教程
2022/05/30 Servers
java实现自定义时钟并实现走时功能
2022/06/21 Java/Android