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 相关文章推荐
Javascript String对象扩展HTML编码和解码的方法
Jun 02 Javascript
JQuery中DOM加载与事件执行实例分析
Jun 13 Javascript
js实现兼容性好的微软官网导航下拉菜单效果
Sep 07 Javascript
Node.js与Sails ~项目结构与Mvc实现及日志机制
Oct 14 Javascript
javascript中this指向详解
Apr 23 Javascript
js 弹出对话框(遮罩)透明,可拖动的简单实例
Jul 11 Javascript
javascript与jquery动态创建html元素示例
Jul 25 Javascript
JavaScript中原型链存在的问题解析
Sep 25 Javascript
详解MVC如何使用开源分页插件(shenniu.pager.js)
Dec 16 Javascript
微信小程序中顶部导航栏的实现代码
Mar 30 Javascript
一次记住JavaScript的6个正则表达式方法
Feb 22 Javascript
深入浅析js原型链和vue构造函数
Oct 25 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获取目录所有文件并将结果保存到数组(实例)
2013/10/25 PHP
PHP采集类Snoopy抓取图片实例
2014/06/19 PHP
YII框架模块化处理操作示例
2019/04/26 PHP
thinkphp整合系列之极验滑动验证码geetest功能
2019/06/18 PHP
JavaScript Cookie的读取和写入函数
2009/12/08 Javascript
jQuery操作CheckBox的方法介绍(选中,取消,取值)
2014/02/04 Javascript
JS实现将人民币金额转换为大写的示例代码
2014/02/13 Javascript
jQuery中has()方法用法实例
2015/01/06 Javascript
jquery+ajax实现跨域请求的方法
2015/01/20 Javascript
javascript实时获取鼠标坐标值并显示的方法
2015/04/30 Javascript
javascript数组常用方法汇总
2016/09/10 Javascript
jQuery实现的图片轮播效果完整示例
2016/09/12 Javascript
jQuery序列化后的表单值转换成Json
2017/06/16 jQuery
JS实现定时任务每隔N秒请求后台setInterval定时和ajax请求问题
2017/10/15 Javascript
element el-input directive数字进行控制
2018/10/11 Javascript
Python中的自定义函数学习笔记
2014/09/23 Python
Django查找网站项目根目录和对正则表达式的支持
2015/07/15 Python
Python中字符串格式化str.format的详细介绍
2017/02/17 Python
JPype实现在python中调用JAVA的实例
2017/07/19 Python
windows 下python+numpy安装实用教程
2017/12/23 Python
用python与文件进行交互的方法
2018/03/01 Python
破解安装Pycharm的方法
2018/10/19 Python
Python制作exe文件简单流程
2019/01/24 Python
Python修改文件往指定行插入内容的实例
2019/01/30 Python
Python3网络爬虫开发实战之极验滑动验证码的识别
2019/08/02 Python
如何使用python的ctypes调用医保中心的dll动态库下载医保中心的账单
2020/05/24 Python
Python带参数的装饰器运行原理解析
2020/06/09 Python
CSS3的resize属性使用初探
2015/09/27 HTML / CSS
澳大利亚时尚前卫设计师珠宝在线:Amber Sceats
2017/10/04 全球购物
BIBLOO波兰:捷克的一家在线服装店
2018/03/09 全球购物
绿化先进工作者事迹材料
2014/01/30 职场文书
环保建议书100字
2014/05/14 职场文书
心理咨询专业自荐信
2014/07/07 职场文书
群众路线教育实践活动个人对照检查材料
2014/09/22 职场文书
学校就业保障协议书
2019/06/24 职场文书
关于PostgreSQL JSONB的匹配和交集问题
2021/09/14 PostgreSQL