目录快车
- 目标
- 实现
- 常规做法
- 步骤
- 弊端
- 解决方案
- 步骤
- 弊端
- 优化方案
- 温馨提示
目标
秒杀倒计时 前端与服务器时间统一 ,误差不超过1000ms(这个误差值可以根据自己的业务调整)
实现
常规做法
步骤
一般情况下要实现前后端时间的统一,肯定不能用本地时间作为基准进行倒计时,因为本地时间与服务器时间极有可能有误差,所以常规做法是在初次请求数据的时候把服务器时间拿过来,然后通过计时器计时
弊端
首先这种方式会存在一个响应时间的问题,也就是说在服务端拿到时间之后返回给前端时,由于网络延迟的问题,前端真正拿到这个时间数据的时候并不能保证它是服务器的当前时间,因为还有一个响应时间的误差在里面;
其次通过计时器计时,比如setTimeout、setInterval 这种内置方法,这个同样会存在误差,不同平台的误差不一样,会被机器性能、内存占用等多方面因素影响,一分钟有可能会误差几秒钟,这种差值是无法被接受的;
还有一种做法是每秒请求一次服务器拿时间,emmm…这个不是常规做法,这是自杀式方案,勿用!
解决方案
步骤
既然是解决方案,肯定是要解决以上常规做法带来的弊端,下面我们看一下具体实现
首先是响应时间的问题,这个很好解决,直接把响应时间拿到之后加上就行了,我们暂且称为服务器矫正时间,用ST表示;
主要问题在于如何缩小在计时过程中的毫秒甚至秒级误差,既然计时器方法被抛弃了,那么我们只有一个办法了,就是获取本地时间,这样可以确保前端和后端的时间精度是一致的,获取本地时间又不能完全使用本地时间,那么就用本地时间(用LT表示)与ST计算得到一个差值(C1表示),再用本地时间加上这个差值,它就是服务器时间,也就是 ST=LT+C1 ,所以说我们可以通过定时器每次请求本地时间就可以了,这样能够保证在计时过程中的时间精度;
弊端
这种方案并不是完全可行,还有一个问题就是在定时获取本地时间的过程中,本地时间很有可能被修改,那这个方案就不灵了
优化方案
在以上的基础上,我们可以把每次定时获取的本地时间通过变量记录下来,保证在本轮获取时间的时候能够先得到上次的时间(BT表示),,我们还需要一个预期时间(ZT表示),因为我们很轻易可以拿到每次定时遍历的时间周期(S表示),也就是说比如每500毫秒获取一次时间,那么S=500ms,所以 ZT=BT+S,还要定义一个常量作为预设值(Z表示),这个预设值是预先定义好的,用来控制误差,是预期时间和实际获取时间的误差范围,也就是说,我们拿到实际获取到的时间之后,与预期时间作比较得到差值(C2表示),C2如果超出预设值,那么继续纠偏,所以最终
if ( C2>Z ) {
ST=LT+C1+C2
} else{
ST=LT+C1
}
温馨提示
如果参加抢购什么的,千万别用IE内核的浏览器,性能问题会致使一些网站的倒计时与服务器时间有误差,最好使用火狐或者谷歌浏览器,Safari也是个不错的选择,这样可以很大程度上避免性能问题造成的时间误差,接下来就是拼手速了,拜拜了您呐