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 相关文章推荐
JS 容错处理代码, 屏蔽错误信息
Mar 09 Javascript
jQuery的实现原理的模拟代码 -5 Ajax
Aug 07 Javascript
基于Jquery 解决Ajax请求的页面 浏览器后退前进功能,页面刷新功能实效问题
Dec 11 Javascript
jquery插件开发注意事项小结
Jun 04 Javascript
javascript关于继承的用法汇总
Dec 20 Javascript
JavaScript输出当前时间Unix时间戳的方法
Apr 06 Javascript
Javascript中的arguments对象
Jun 20 Javascript
基于jQuery实现表格的查看修改删除
Aug 01 Javascript
AngularJS模板加载用法详解
Nov 04 Javascript
js replace()去除代码中空格的实例
Feb 14 Javascript
bootstrap table表格客户端分页实例
Aug 07 Javascript
JavaScript学习教程之cookie与webstorage
Jun 23 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中用header图片地址 简单隐藏图片源地址
2008/04/09 PHP
PHP获取数组中单列值的方法
2017/06/10 PHP
Laravel框架实现调用百度翻译API功能示例
2019/05/30 PHP
javascript qq右下角滑出窗口 sheyMsg
2010/03/21 Javascript
jQuery中add实现同时选择两个id对象
2010/10/22 Javascript
纯js实现背景图片切换效果代码
2010/11/14 Javascript
jquery maxlength使用说明
2011/09/09 Javascript
浅谈javascript的原型继承
2012/07/25 Javascript
javascript for循环从入门到偏门(效率优化+奇特用法)
2012/08/01 Javascript
jQuery.query.js 取参数的两点问题分析
2012/08/06 Javascript
jquery实现不同大小浏览器使用不同的css样式表的方法
2014/04/02 Javascript
javascript中的throttle和debounce浅析
2014/06/06 Javascript
javascript 自定义回调函数示例代码
2014/09/26 Javascript
使用javascript将时间转换成今天,昨天,前天等格式
2015/06/25 Javascript
jquery实现表单验证简单实例演示
2015/11/23 Javascript
js图片跟随鼠标移动代码
2015/11/26 Javascript
jquery中用jsonp实现搜索框功能
2016/10/18 Javascript
总结js函数相关知识点
2018/02/27 Javascript
详解webpack的proxyTable无效的解决方案
2018/06/15 Javascript
python使用cPickle模块序列化实例
2014/09/25 Python
python3 cvs将数据读取为字典的方法
2018/12/22 Python
python和c语言的主要区别总结
2019/07/07 Python
基于Python和C++实现删除链表的节点
2020/07/06 Python
Python依赖包迁移到断网环境操作
2020/07/13 Python
英国设计的甲板鞋和船鞋:Chatham
2018/12/06 全球购物
施华洛世奇匈牙利官网:SWAROVSKI匈牙利
2019/07/06 全球购物
美国领先的眼镜和太阳镜在线零售商:Glasses.com
2019/08/26 全球购物
大学毕业生简单自荐信
2013/11/05 职场文书
写给学生的新学期寄语
2014/01/18 职场文书
上班玩手机检讨书
2014/02/17 职场文书
法院信息化建设方案
2014/05/21 职场文书
重大事项社会稳定风险评估方案
2014/06/15 职场文书
贷款委托书
2014/08/01 职场文书
安娜卡列尼娜观后感
2015/06/11 职场文书
求职信如何撰写?
2019/05/22 职场文书
css position fixed 左右双定位的实现代码
2021/04/29 HTML / CSS