有些时候我们会遇到页面倒计时的需求,比如一个活动限时1个小时抢购,需要在页面上显示活动还有多久结束。

一般这种倒计时呢,一般有两种方法来解决:一是后端返回距离结束时候还有多久的时间差;二是返回服务器当前时间和活动截至时间,客户端自己计算时间差然后倒计时。

今天我们就来讨论一下上述的第二种方案,看看有没有什么问题。

方案讨论

其实我们一直都有一个疑惑,就是ajax请求回来的服务器当前时间和真实的服务器当前时间到底有多大误差?因为ajax一来一回是需要时间的,而且服务器处理也是需要时间的,大致过程如下:

background Layer 1 客户端 服务端 1.客户端发起请求 2.服务端处理 3.服务端返回数据

不过实际在客户端接受到数据之后,并不是直接使用的,需要转换才能使用,具体可以参考ajax的readyState状态,一共有五种状态。

0: (Uninitialized) the send( ) method has not yet been invoked.

1: (Loading) the send( ) method has been invoked, request in progress.

2: (Loaded) the send( ) method has completed, entire response received.

3: (Interactive) the response is being parsed.

4: (Completed) the response has been parsed, is ready for harvesting.

状态0表示send()方法没有发送,1表示send()已经发送,2表示send()方法发送完毕,已经接到所有数据,3表示将接收到的数据按照返回格式进行转换,4表示转换完毕,可以使用,readyState版的ajax发送如下:

background Layer 1 客户端 服务端 1.readyState==1 2.服务端处理 3.readyState==2 4.readyState==3 5.readyState==4

通常我们获取数据一般都是在readyState为4的时候才获取(complete,success,error),也就是说,如果你是获取后端当前时间的话,已经经过了readyState为3的时候,这当然是不够准确的,最好的情况我们是在readyState为2的时候拿到服务器时间,可是readyState为2的时候,数据都没有准备好,怎么拿呢?

我们可以看到,每次返回的Response Header中可以看到Date这一栏,这是是从服务器返回的时间。当readyState为2的时候,其实已经可以获取这个Date了。通过xhr.getResponseHeader('Date')可以获取到。

这个是服务器的时间不假,可是这是哪个时间呢?是请求刚到服务器的时间还是请求返回客户端时的时间呢?为此,我做了一个实验,就是将一个请求内做一个50000000次的循环(模拟复杂耗时操作),然后分别输出循环前后的服务器当前时间,可以看到以下结果:

我们可以很清楚的看到,这个Response Header中的Date是请求刚到服务器的时间。因此我们可以描绘出一个时间走势图:

background Layer 1 客户端 服务端 1.readyState==1 2.服务端处理 3.readyState==2 v_t_1 v_t_2 r_t_1 v_t_1是客户端准备发送请求的客户端时间,对应的readyState为1 v_t_2是客户端收到返回数据的客户端时间,对应的readyState为2 r_t_1是Response Header中的Date,是客户端到达后端的时间 d1 d2 d3 d1代表客户端请求到达后端花费时间 d2代表客服务端处理花费的时间 d3代表数据从后端到达客户端花费的时间

其实我们没办法计算出准确的后端当前时间,但是我们可以计算出一个区间范围。

首先呢,最小值就是r_t_1,它和真实的后端当前时间相比,少了服务器处理时间和数据返回的时间(d2+d3)。

最大值是v_t_2+(r_t_1-v_t_1),这个数值和后端当前时间相比,多了一个从客户端请求到后端的时间(d1)。

我们可以给它们取个平均值,以减少和真实之间的误差。

实例解说

假设客户端当前时间为12:00:00,后端当前时间为12:00:10,客户端到达后端时间为1s,后端处理时间为2s,后端返回客户端时间为3s。

那么v_t_1为12:00:00,r_t_1为12:00:11,v_t_2为12:00:06,最小值为12:00:11,最大值为12:00:17,平均值为12:00:14,真实后端时间为:12:00:16。

从上面的例子来看,似乎最大值更加贴近真实后端时间,那是因为我的数据都是伪造的,在相对稳定的网络环境中,客户端到后端以及后端到客户端的时间应该是差不多的,因此我们假设如下:

假设客户端当前时间为12:00:00,后端当前时间为12:00:10,客户端到达后端时间为5s,后端处理时间为2s,后端返回客户端时间为5s。

那么v_t_1为12:00:00,r_t_1为12:00:15,v_t_2为12:00:12,最小值为12:00:15,最大值为12:00:27,平均值为12:00:21,真实后端时间为:12:00:22。

看到没,这个时候平均值和真实时间就很接近了,不过还是有误差。不过我们可以发现,如果后端处理时间很快,快到0s的话,那么在网络相对稳定的情况下,平均值就等于后端真实时间了:

假设客户端当前时间为12:00:00,后端当前时间为12:00:10,客户端到达后端时间为5s,后端处理时间为0s,后端返回客户端时间为5s。

那么v_t_1为12:00:00,r_t_1为12:00:15,v_t_2为12:00:10,最小值为12:00:15,最大值为12:00:25,平均值为12:00:20,真实后端时间为:12:00:20。

总结

现在我想应该知道如何获取更加真实的后端时间了,第一用Response Header中的Date,第二取它们的平均值,第三,为了是平均值更加贴近真实的后端当前时间,我们后端处理的内容一定不要太多,越少越好。

DEMO下载

点击下载 [0积分]一共下载0

其他文章

0
我要评论

评论

返回
×

我要评论

回复:

昵称:(昵称不超过20个字)

图片:

提交
还可以输入500个字