javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > js浏览器缓存判断

JS使用Expires max-age判断缓存过期的浏览器实例

作者:DiracKeeko

这篇文章主要为大家介绍了JS使用Expires max-age判断缓存过期的浏览器实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

Expires (http1.0)

在HTTP Header中通过Expires字段 传递一个GMT格式的字符串。

举例:

Expires: Wed Feb 20 2019 11:25:41 GMT

Cache-Control: max-age=<seconds> (http1.1)
在HTTP Header中通过Cache-Control字段中的值max-age传递一个max-age=<seconds>的字符串。

举例:

Cache-Control: max-age=3600

如果Expires和Cache-Control: max-age=<seconds>二者同时存在,max-age 的优先级高于 expires
(浏览器会根据 max-age 指令的值来决定缓存的有效期,而忽略 Expires)

上面这段话是在中文互联网上出现的很多的内容,表述可能不一样,但是内容就是这些了。

那么浏览器到底怎么判断缓存过期?用max-age判断缓存过期是否与本地时间有关?

在中文互联网的论坛中,基本都是说Expires字段设置的缓存过期时间会受本地时间影响,max-age设置的缓存过期时间不会受本地时间影响。

max-age设置缓存后

-那么在使用max-age设置缓存后,浏览器到底怎么判断缓存过期?判断缓存过期是否与本地时间有关?

看我下面这个问题场景。

如果HTTP响应中包含以下头部:

Date: Wed, 16 Oct 2019 07:42:37 GMT
Cache-Control: max-age=3600

按照中文互联网上的常见表述

"浏览器记录下max-age的时间点是通过在HTTP响应中的Date头部来完成的。

Date头部指示了服务器响应请求的时间,它通常以格林威治标准时间 (GMT) 格式表示。"

那么浏览器会计算出资源的有效期截止时间为Wed, 16 Oct 2019 08:42:37 GMT,(即当前时间加上max-age指定的秒数) 。浏览器会记录这个时间点,以便后续请求时判断资源是否过期。

问题

当浏览器第二次发请求的时候,浏览器是否需要找到一个时间节点T2 来判定T2与 Wed, 16 Oct 2019 08:42:37 GMT的大小关系?

-如果需要T2,那么T2如何取值? (是否受本地时间的影响?)

-如果不需要T2,那么浏览器通过什么来判定这个缓存是否过期?

下面开始进入正题,查证的过程中我发现有不少(错误的)内容在中文互联网上被互相转载,站站相传,属实离谱。
本文引用材料均有出处。各位读者可以点link查看。

以chromium内核的实现为例来说明

1、判断缓存是否过期

https://github.com/chromium/chromium/blob/main/net/http/http_response_headers.cc#L1107-L1114

公式如下:

response_is_fresh = (freshness_lifetime > current_age)

这里有个字段 response_is_fresh (相应依旧新鲜)
字面理解,如果response_is_fresh为true,则表示缓存未过期。
如果保鲜时间(freshness_lifetime) 大于 当前经历时间(current_age),则表示缓存未过期。

再往下看,找到freshness_lifetime和current_age的计算方法。

2、freshness_lifetime的计算 ( 保鲜时间(有效期)的计算 )

https://github.com/chromium/chromium/blob/main/net/http/http_response_headers.cc#L1141-L1163

这段话里明确说明max-age的优先级大于expires

如果有max-age
freshness_lifetime = max_age_value

如果没有max-age
freshness_lifetime = expires_value - date_value

看1152 1153两行

Note that neither of these calculations is vulnerable to clock skew, since all of the information comes from the origin server

"注意,这两种计算方式都不会受到时钟偏差的影响,因为所有信息都来自于源服务器。"

也就是说,不论是用max-age还是expires计算freshness_lifetime,都不会受到时钟偏差的影响。

3、current_age的计算 ( 当前经历时间的计算 )

https://github.com/chromium/chromium/blob/main/net/http/http_response_headers.cc#L1264-L1332

// From RFC 7234 section 4.2.3:
//
// The following data is used for the age calculation:
//
//    age_value
//
//       The term "age_value" denotes the value of the Age header field
//       (Section 5.1), in a form appropriate for arithmetic operation; or
//       0, if not available.
//
//    date_value
//
//       The term "date_value" denotes the value of the Date header field,
//       in a form appropriate for arithmetic operations.  See Section
//       7.1.1.2 of [RFC7231] for the definition of the Date header field,
//       and for requirements regarding responses without it.
//
//    now
//
//       The term "now" means "the current value of the clock at the host
//       performing the calculation".  A host ought to use NTP ([RFC5905])
//       or some similar protocol to synchronize its clocks to Coordinated
//       Universal Time.
//
//    request_time
//
//       The current value of the clock at the host at the time the request
//       resulting in the stored response was made.
//
//    response_time
//
//       The current value of the clock at the host at the time the
//       response was received.
//
//    The age is then calculated as
//
//     apparent_age = max(0, response_time - date_value);
//     response_delay = response_time - request_time;
//     corrected_age_value = age_value + response_delay;
//     corrected_initial_age = max(apparent_age, corrected_age_value);
//     resident_time = now - response_time;
//     current_age = corrected_initial_age + resident_time;

1264行到1305行,这一段注释里的now,对应下面HttpResponseHeaders::GetCurrentAge这个方法中的current_time(L1328)

The term "now" means "the current value of the clock at the host performing the calculation". A host ought to use NTP ([RFC5905]) or some similar protocol to synchronize its clocks to Coordinated Universal Time.

关于now的注释这里写明了

"now"一词表示"执行计算的主机上时钟的当前值"。主机应该使用NTP([RFC5905])或类似协议将其时间与世界时钟同步。

那么current_age的计算是需要依赖于客户端主机的本地时钟的。

回到这个问题

如果HTTP响应中包含以下头部:

Date: Wed, 16 Oct 2019 07:42:37 GMT
Cache-Control: max-age=3600

当浏览器第二次发请求的时候,浏览器是否需要找到一个时间节点T2来判定T2与 Wed, 16 Oct 2019 08:42:37 GMT的大小关系?

-如果需要T2,那么T2如何取值? (是否受本地时间的影响?)

-如果不需要T2,那么浏览器通过什么来判定这个缓存是否过期?

总结

(chromium内核的)浏览器用的是比较freshness_lifetime(约等于max-age,保鲜时间,是一个时间跨度)和current_age(当前经历时间,也是一个时间跨度)来计算有效期。

不需要时间节点T2。

计算freshness_lifetime用的是服务器时间, 不受本地时间影响。
但计算current_age用到了本地时间(current_time, 也就是注释中的now),而且没法保证本地时间与服务器时间一致。

因此,不论是Expires还是Cache-Control: max-age=<seconds> 计算缓存有效期的时候,都会受到本地时间的影响。

以上就是JS使用Expires max-age判断缓存过期的浏览器实例的详细内容,更多关于js浏览器缓存判断的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文