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 相关文章推荐
Extjs中ComboBox加载并赋初值的实现方法
Mar 22 Javascript
Jquery增加鼠标中间功能mousewheel的实例代码
Sep 05 Javascript
jQuery对Select的操作大集合(收藏)
Dec 28 Javascript
jquery左边浮动到一定位置时显示返回顶部按钮
Jun 05 Javascript
JavaScript更改原始对象valueOf的方法
Mar 19 Javascript
js编写贪吃蛇的小游戏
Aug 24 Javascript
BootStrap智能表单实战系列(九)表单图片上传的支持
Jun 13 Javascript
easyui combotree加载静态数据问题(选不上)解决方法
Dec 26 Javascript
理解javascript中的闭包
Jan 11 Javascript
Element中的Cascader(级联列表)动态加载省\市\区数据的方法
Mar 27 Javascript
Vue 实现分页与输入框关键字筛选功能
Jan 02 Javascript
详解JavaScript中分解数字的三种方法
Jan 05 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
DC这些乐高系列动画电影你看过几部?
2020/04/09 欧美动漫
PHP性能优化 产生高度优化代码
2011/07/22 PHP
PHP的几个常用数字判断函数代码
2012/04/24 PHP
浅谈PHP中output_buffering
2015/07/13 PHP
你不知道的文件上传漏洞php代码分析
2016/09/29 PHP
PHP符合PSR编程规范的实例分享
2016/12/21 PHP
Ecshop 后台添加新功能栏目及管理权限设置教程
2017/11/21 PHP
插件:检测javascript的内存泄漏
2007/03/04 Javascript
javascript 面向对象编程基础:封装
2009/08/21 Javascript
javascript获得CheckBoxList选中的数量
2009/10/27 Javascript
jquery模拟LCD 时钟的html文件源代码
2014/06/16 Javascript
jQuery中next()方法用法实例
2015/01/07 Javascript
JS自定义混合Mixin函数示例
2016/11/26 Javascript
微信小程序 devtool隐藏的秘密
2017/01/21 Javascript
详解webpack3编译兼容IE8的正确姿势
2017/12/21 Javascript
基于vue-cli 打包时抽离项目相关配置文件详解
2018/03/07 Javascript
Vue 实现双向绑定的四种方法
2018/03/16 Javascript
vue鼠标移入添加class样式,鼠标移出去除样式(active)实现方法
2018/08/22 Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
2019/04/18 Javascript
vue2.0实现列表数据增加和删除
2020/06/17 Javascript
vue 验证两次输入的密码是否一致的方法示例
2020/09/29 Javascript
[46:59]完美世界DOTA2联赛PWL S2 GXR vs Ink 第二场 11.19
2020/11/20 DOTA
[46:47]完美世界DOTA2联赛PWL S2 FTD vs Magma 第二场 11.20
2020/11/23 DOTA
Python创建二维数组实例(关于list的一个小坑)
2017/11/07 Python
python进行两个表格对比的方法
2018/06/27 Python
Django实现CAS+OAuth2的方法示例
2019/10/30 Python
opencv3/Python 稠密光流calcOpticalFlowFarneback详解
2019/12/11 Python
CSS3动画之利用requestAnimationFrame触发重新播放功能
2019/09/11 HTML / CSS
利用简洁的图片预加载组件提升html5移动页面的用户体验
2016/03/11 HTML / CSS
HTML5画渐变背景图片并自动下载实现步骤
2013/11/18 HTML / CSS
Hotels.com印度:酒店预订
2019/05/11 全球购物
餐饮业会计岗位职责
2013/12/19 职场文书
我们的节日中秋活动方案
2014/08/19 职场文书
2016年公务员六五普法心得体会
2016/01/21 职场文书
XX部保密工作制度范本
2019/08/27 职场文书
PL350与SW11的比较
2021/04/22 无线电