项目要求:
在前端界面上显示服务器的时间,格式是: yyyy-MM-dd hh:mm:ss 。 且误差控制在肉眼不可察觉
思路:
时间精确到秒,总不能一秒请求一次后台接口获取(资源耗费巨大,一段时间就会导致界面卡死)。 所以采用,一分钟请求一次接口进行时间校准,一分钟内,前端自行进行+1 处理来模拟秒数。
问题:
一开始采用,setInterval 做定时器+1 ,发现,运行一段时间,会有1-2s 的误差(其中还要解决定时器休眠,抖动等问题)
后采用requestAnimationFrame 解决以上问题。
但是新的问题来了,继续测试,依旧发现,会有半秒到一秒的误差。
最后让后台接口给我反馈回来,服务器当前时间的毫秒。 做毫秒的处理,才解决误差问题
最终代码如下:
代码
//获取服务器的时间
async set_serve_time(){
clearTimeout(this.servetimer);
window.cancelAnimationFrame(this.timer_auto);
const result = await getServeTimeApi(); //请求后台接口,获取服务器时间
let startTime = Date.now();
if(result.meta.status == 200){
//console.log(result.data, 'result.data')
let data = result.data.sec; //服务器时间 yyyy-MM-dd hh:mm:ss
let ms_data = Number(result.data.msec); //服务器时间的 毫秒
startTime = startTime - ms_data; //开始时间去除服务器时间的毫秒; 减少误差
this.$store.commit('setServe_ymd', data.split(' ')[0]);
this.$store.commit('setServe_hms', data.split(' ')[1]);
let data_stamp = Date.parse(data) ; //日期转为时间戳(s)
let loop = () => {
let endTime = Date.now();
let diffTime = endTime - startTime;
if (diffTime >= 1000) {
startTime = endTime = Date.now();
data_stamp = data_stamp + diffTime ;
let data_format = dateFormat_one(data_stamp, 'yyyy-MM-dd hh:mm:ss'); //时间戳转日期
const [time_ymd, time_hms] = data_format.split(' ');
this.$store.commit('setServe_ymd', time_ymd);
this.$store.commit('setServe_hms', time_hms);
}
this.timer_auto = window.requestAnimationFrame(loop);
}
loop();
}else{
clearTimeout(this.servetimer);
window.cancelAnimationFrame(this.timer_auto);
this.$store.commit('setServe_ymd', '-');
this.$store.commit('setServe_hms', '-');
}
this.servetimer = setTimeout(this.set_serve_time, 1 * 60 * 1000);
},
解释
其中,startTime = startTime - ms_data; 至关重要。 因为,仔细思考全过程,如果我们不考虑服务器时间的毫秒,假设当前服务器时间是17:17:17: 980 , 前端拿到的时候就是17:17:17 , 但此时服务器真正的时间已经是17:17:18了 ,这个误差就大了。
再加上从后台获取到服务器时间,这个过程本身有一定是时间延迟。
最终测试,时间误差控制做了肉眼不可识别的程度。









网友评论