不得不知道的浏览器http缓存

浏览器虽然发现了本地有该资源的缓存,但是不确定是否是最新的,于是想服务器询问,若服务器认为浏览器的缓存版本还可用,那么便会返回304。

强缓存和协商缓存。

1.浏览器请求某资源,通过header判断是否强缓存,若是强缓存,则从本地直接获取缓存文件,不发请求到浏览器
2.若不是强缓存,发送请求到服务器,服务器通过一些request header确定是否是协商缓存,如果是,服务器将请求返回,但不返回资源,而是让客户端从本地缓存获取资源
3.强缓存和协商缓存,资源都是本地,只是强缓存不会发送请求到服务器,协商缓存会发送请求到服务器。
4.不是协商缓存,则浏览器将资源发送客户端。

强缓存:服务端第一次响应请求时,告知浏览器还存在本地,设定时间,时间之内还获取该资源就从本地获取。
Expires Cache-Control两个响应首部字段告知过期时间和最大生命周期。再次请求从缓存中找资源,若请求时间比Expires设定时间早则可用本地资源。
http1.1 Cache-Control缓存资源最大生命周期,秒为单位。一起使用以Cache-Control为主。
协商缓存:文件最后修改时间,服务器判断资源是否更新,未更新返回304表示not modified,浏览器从缓存加载。
LastModified:资源最后更新时间,随服务器返回。if-modified-Since请求首部字段,通过比较两个时间判断资源是否修改。没有修改则协商缓存。

过程描述:

1.浏览器第一次请求资源,服务器响应,返回资源,响应头加Last-Modified。
2.浏览器再次请求资源,在请求头加上if modified since,该值为上次Last-Modified的值
3.服务器接受请求,将ifmodifiedsince值和资源最后修改值做对比,若一致则返回304,协商缓存。
  • Etag周期性重写资源,但资源没变化,加注释等无关紧要信息。用Etag区分两个资源是否一致,随response返回和请求头的if-none-match相比较,判断资源在两次请求中是否修改,未修改则协商缓存。
  • 还有三种缓存方式:application cache,cookie,localstorage,sessionstorage

那么,前端怎么实现呢?

了解ifModified

ifModified (Boolean) : (默认: false) 仅在服务器数据改变时获取新数据。使用 HTTP 包 Last-Modified 头信息判断。
由ifModified的定义可知,当ifModified设为true时,请求头会加上If-Modified-Since, If-Modified-Since是标准的http请求头标签,在发送http请求时,把浏览器端缓存页面的最后修改时间一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。
如果时间一致,那么返回http状态码304(不返回文件内容)
如果时间不一致,就返回http状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。

了解Last-Modified

Last-Modified:表示该文件的最后修改日期,是文件属性和服务端没关系
对于静态资源文件这是一个很有用的属性,请求静态资源文件时,请求头会携带一个If-Modified-Since:xxx(时间)属性,该属性是上一次请求时获取到的Last-Modified时间,如果本次请求的请求头时间与响应头时间一致,则返回304状态码,告诉浏览器你当前拥有的页面是最新的不需要获取新的数据

实现

function getAjax(url, sendData, state = true) {
    return new Promise((resolve, reject) => {
        $.ajax({
            url: url,
            data: sendData,
            type: 'get',
            dataType: 'json',
            cache: !state, //是否使用浏览器的缓存数据
            ifModified: state,//是否向服务器询问数据更新情况
            success(data, des, status) {
                if (status.status === 200) {
                    if (data.code === 200) {
                        return resolve(data.data);
                    } else {
                        return reject({code: data.code, message: data.message});
                    }
                }
                if (status.status === 304) {
                    getAjax(url, sendData, false)
                    .then(data => {
                        resolve(data);
                    })
                    .catch(data => {
                        reject(data);
                    });
                }
            }, error() {
                return reject({code: 503, message: '数据无法加载,请刷新重试!'});
            }
        });
    });
}

分析

  • getAjax中传入3个参数,url接口地址,sendData 传输的数据,state状态值【代表ifModified的状态】
  • 首先向后台询问数据是否更新,ifModified的状态为true,不使用浏览器的缓存数据,cache设false
  • 当http状态码返回200时,说明数据更新了,直接使用服务器传输过来的新数据;
  • 当http状态码返回304时,说明数据没有发生改变,服务器不返回新数据,则向浏览器缓存请求数据,此时cache设true,ifModified的状态为false,不需要询问服务器数据是否更新。

总结:使用缓存的目的就是在于减少计算,IO,网络等时间,可以快速的返回,特别是流量比较大的时候,可以节约很多服务器带宽和压力。

相关推荐