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动态呼叫函数(两种方式)
May 03 Javascript
window.location 对象所包含的属性
Oct 10 Javascript
jQuery中remove()方法用法实例
Dec 25 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 图片库
Jan 09 Javascript
ECMAScript6函数剩余参数(Rest Parameters)
Jun 12 Javascript
基于bootstrap实现广告轮播带图片和文字效果
Jul 22 Javascript
详解Angular的双向数据绑定(MV-VM)
Dec 26 Javascript
Node.js五大应用性能技巧小结(必须收藏)
Aug 09 Javascript
ES6扩展运算符的用途实例详解
Aug 20 Javascript
AngularJS下$http服务Post方法传递json参数的实例
Mar 29 Javascript
微信小程序wx.uploadfile 本地文件转base64的实现代码
Jun 28 Javascript
微信小程序自定义顶部组件customHeader的示例代码
Jun 03 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/01/23 PHP
ThinkPHP视图查询详解
2014/06/30 PHP
PHP魔术方法以及关于独立实例与相连实例的全面讲解
2016/10/18 PHP
PHP封装的page分页类定义与用法完整示例
2018/12/24 PHP
php生成微信红包数组的方法
2019/09/05 PHP
js滚动条多种样式,推荐
2007/02/05 Javascript
基于JQuery的asp.net树实现代码
2010/11/30 Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战二)
2013/08/21 Javascript
动态载入js提高网页打开速度的方法
2014/07/04 Javascript
input输入框鼠标焦点提示信息
2015/03/17 Javascript
JS+CSS实现自适应选项卡宽度的圆角滑动门效果
2015/09/15 Javascript
vue 2.0封装model组件的方法
2017/08/03 Javascript
nodejs Assert中equal(),strictEqual(),deepEqual(),strictDeepEqual()比较
2017/09/18 NodeJs
JS返回页面时自动回滚到历史浏览位置
2018/09/26 Javascript
egg.js的基本使用和调用数据库的方法示例
2019/05/18 Javascript
Python open读写文件实现脚本
2008/09/06 Python
Python中的choice()方法使用详解
2015/05/15 Python
Python实现图片转字符画的示例
2017/08/22 Python
读取json格式为DataFrame(可转为.csv)的实例讲解
2018/06/05 Python
Tensorflow 同时载入多个模型的实例讲解
2018/07/27 Python
python给微信好友定时推送消息的示例
2019/02/20 Python
Python实现的列表排序、反转操作示例
2019/03/13 Python
python django下载大的csv文件实现方法分析
2019/07/19 Python
Win10里python3创建虚拟环境的步骤
2020/01/31 Python
高级3D打印市场:Gambody
2019/12/26 全球购物
俄罗斯最大的在线手表商店:Bestwatch.ru
2020/01/11 全球购物
俄罗斯三星品牌商店:Samsungstore
2020/04/05 全球购物
VC++笔试题
2014/10/13 面试题
将"引用"作为函数返回值类型的格式、好处和需要遵守的规则
2016/02/09 面试题
表扬信格式
2014/01/12 职场文书
本科生就业推荐信
2014/05/19 职场文书
趣味运动会广播稿
2014/09/13 职场文书
小学生九一八纪念日83周年演讲稿500字
2014/09/17 职场文书
党员对照检查剖析材料
2014/10/13 职场文书
地球上的星星观后感
2015/06/02 职场文书
优秀员工演讲稿
2019/06/21 职场文书