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自执行函数的几种不同写法的比较
Aug 16 Javascript
Js 获取Gridview选中行的内容操作步骤
Feb 05 Javascript
javaScript实现滚动新闻的方法
Jul 30 Javascript
使用angularjs创建简单表格
Jan 21 Javascript
JS判断浏览器是否安装flash插件的简单方法
Sep 13 Javascript
原生js实现打字动画游戏
Feb 04 Javascript
深入理解React高阶组件
Sep 28 Javascript
jQuery中ajax获取数据赋值给页面的实例
Dec 31 jQuery
p5.js入门教程之小球动画示例代码
Mar 15 Javascript
利用Blob进行文件上传的完整步骤
Aug 02 Javascript
微信小程序实现日历小功能
Nov 18 Javascript
JavaScript缓动动画函数的封装方法
Nov 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
escape unescape的php下的实现方法
2007/04/27 PHP
php 修改上传文件大小限制实例详解
2016/10/23 PHP
php数组指针操作详解
2017/02/14 PHP
PHP fopen函数用法实例讲解
2019/02/15 PHP
网页常用特效代码整理
2006/06/23 Javascript
Jquery拖拽并简单保存的实现代码
2010/11/28 Javascript
JS中动态添加事件(绑定事件)的代码
2011/01/09 Javascript
如何学习Javascript入门指导
2013/11/01 Javascript
使用upstart把nodejs应用封装为系统服务实例
2014/06/01 NodeJs
jQuery常用数据处理方法小结
2015/02/20 Javascript
JavaScript Array对象详解
2016/03/01 Javascript
JavaScript实现简单的日历效果
2016/09/25 Javascript
详谈$.data()的用法和作用
2017/02/13 Javascript
利用node.js本地搭建HTTP服务器
2017/04/19 Javascript
js实现Tab选项卡切换效果
2020/07/17 Javascript
JavaScript事件对象event用法分析
2018/07/27 Javascript
Vue项目引进ElementUI组件的方法
2018/11/11 Javascript
微信小程序点击图片实现长按预览、保存、识别带参数二维码、转发等功能
2019/07/20 Javascript
JS实现在线ps功能详解
2019/07/31 Javascript
微信小程序转化为uni-app项目的方法示例
2020/05/22 Javascript
jQuery 动态粒子效果示例代码
2020/07/07 jQuery
[42:00]完美世界DOTA2联赛PWL S3 Phoenix vs INK ICE 第一场 12.13
2020/12/17 DOTA
教你安装python Django(图文)
2013/11/04 Python
各种Python库安装包下载地址与安装过程详细介绍(Windows版)
2016/11/02 Python
python读取文本中数据并转化为DataFrame的实例
2018/04/10 Python
Python3爬虫关于识别点触点选验证码的实例讲解
2020/07/30 Python
基于PyInstaller各参数的含义说明
2021/03/04 Python
HTML5的自定义属性data-*详细介绍和JS操作实例
2014/04/10 HTML / CSS
StubHub新加坡:购买和出售全球活动门票
2017/03/10 全球购物
银行职员思想汇报
2013/12/31 职场文书
难忘的一课教学反思
2014/04/30 职场文书
锦旗赠语
2015/06/23 职场文书
css display table 自适应高度、宽度问题的解决
2021/05/07 HTML / CSS
python实现剪贴板的操作
2021/07/01 Python
javascript实现计算器功能详解流程
2021/11/01 Javascript
Python中的变量与常量
2021/11/11 Python