资讯专栏INFORMATION COLUMN

JavaScript 前端倒计时纠偏实现

EsgynChina / 856人阅读

摘要:前端网页倒计时是非常常见的应用,我们在各大购物网站的秒杀活动中总是能见到它的身影。这个方法简单但也有点粗暴,下面提供一种方法,能够一定程度上不依赖服务端实现倒计时的纠偏。

前端网页倒计时是非常常见的应用,我们在各大购物网站的秒杀活动中总是能见到它的身影。但是在实际情况中,我们常常会发现当网页不刷新、让倒计时程序持续运行时,显示时间相比实际时间会越来越慢,相信大家也有在秒杀时间即将到来时不停刷新页面的经历。原因自然也不难理解:倒计时通常使用定时器(setTimeout 或者 setInterval )实现,而 JavaScript 的单线程特性使得主线程执行栈中出现阻塞时,任务队列中的异步任务并不能及时执行,因此浏览器并不能保证在定时器设置的时间结束后代码总是被准时执行,这就造成了倒计时的偏差。

一般的解决方法是前端定时向服务器发送请求获取最新的时间差来校准倒计时时间,主动(程序里设置定时请求)或被动的(F5 已被用户按坏)区别而已。这个方法简单但也有点粗暴,下面提供一种方法,能够一定程度上不依赖服务端实现倒计时的纠偏。代码非原创,时间久远忘了出处,在此记录一下学习过程以免遗忘。如有侵权请联系我。

首先我们需要模拟主线程阻塞的环境,同时又不能让主线程一直阻塞:

setInterval(function(){ 
  let j = 0
  while(j++ < 100000000)
}, 0)

然后是主要的代码:

const interval = 1000
let ms = 50000,  // 从服务器和活动开始时间计算出的时间差,这里测试用 50000 ms
let count = 0
const startTime = new Date().getTime()
let timeCounter
if( ms >= 0) {
  timeCounter = setTimeout(countDownStart, interval)
}
 
function countDownStart () {
   count++
   const offset = new Date().getTime() - (startTime + count * interval) // A
   let nextTime = interval - offset
   if (nextTime < 0) { 
       nextTime = 0 
   }
   ms -= interval
   console.log(`误差:${offset} ms,下一次执行:${nextTime} ms 后,离活动开始还有:${ms} ms`)
   if (ms < 0) {
     clearTimeout(timeCounter)
   } else {
     timeCounter = setTimeout(countDownStart, nextTime)
   }
 }

代码的基本原理并不复杂:通过递归调用 setTimeout 进行倒计时操作的执行。而每次执行函数时会维护一个 count 变量,用以记录已经执行过的倒计时次数,使用代码 A 处的公式可计算出当前执行倒计时的时间与实际应执行时间的偏差,进而可以计算出下次执行倒计时的时间。

本文首发于我的博客(点此查看),欢迎关注。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98042.html

相关文章

  • JS 异步的实现

    摘要:由于引擎同一时间只执行一段代码这是由单线程的性质决定的,所以每个代码块阻塞了其它异步事件的进行。这意味着浏览器将等待着一个新的异步事件发生。异步的任务执行的顺序是不固定的,主要看返回的速度。 我们经常说JS是单线程的,比如node.js研讨会上大家都说JS的特色之一是单线程的,这样使JS更简单明了,可是大家真的理解所谓JS的单线程机制吗?单线程时,基于事件的异步机制又该当如何,这些知识...

    sihai 评论0 收藏0
  • javascript日期类型(Date)与php日期类型详解

    摘要:注意客户端与服务器日期进行传输的时候一般都是用大整数时间戳进行传输。 前言 一个网站的开发需要要UI、前端、后端三种工程师。现在的企业在招聘前端工程师的时候一般都要求其了解或者掌握一些后端的知识。因此,此文章主要介绍javascript的日期类型,也粗略的介绍一下php的日期类型,以及二者是如何交互数据的。 时间戳 什么是时间戳 时间戳是从格林威治时间1970年1月1日(00:0...

    chemzqm 评论0 收藏0
  • javascript日期类型(Date)与php日期类型详解

    摘要:注意客户端与服务器日期进行传输的时候一般都是用大整数时间戳进行传输。 前言 一个网站的开发需要要UI、前端、后端三种工程师。现在的企业在招聘前端工程师的时候一般都要求其了解或者掌握一些后端的知识。因此,此文章主要介绍javascript的日期类型,也粗略的介绍一下php的日期类型,以及二者是如何交互数据的。 时间戳 什么是时间戳 时间戳是从格林威治时间1970年1月1日(00:0...

    BDEEFE 评论0 收藏0
  • Javascript学习总结 - JS基础系列三

    摘要:案例每隔毫秒调用函数并显示时间。当点击按钮时,停止时间代码如下计时器每隔毫秒调用函数,并将返回值赋值给计时器计时器,在载入后延迟指定时间后去执行一次表达式仅执行一次。该值标识要取消的延迟执行代码块。 简述 本系列将持续更新Javascript基础部分的知识,谁都想掌握高端大气的技术,但是我觉得没有一个扎实的基础,我认为一切高阶技术对我来讲都是过眼云烟,要成为一名及格的前端工程师,必须把...

    zlyBear 评论0 收藏0
  • 26天学通前端开发(配资料)

    摘要:网上有很多前端的学习路径文章,大多是知识点罗列为主或是资料的汇总,数据量让新人望而却步。天了解一个前端框架。也可以关注微信公众号晓舟报告,发送获取资料,就能收到下载密码,网盘地址在最下方,获取教程和案例的资料。 前言 好的学习方法可以事半功倍,好的学习路径可以指明前进方向。这篇文章不仅要写学习路径,还要写学习方法,还要发资料,干货满满,准备接招。 网上有很多前端的学习路径文章,大多是知...

    blair 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<