3

这篇文章只是对我觉得常用的缓存方法的学习记录。我是通过参考下面参考资料做的总结,大家可以直接看参考链接里的文章,他们的记录更全面且带图。

一、http缓存

浏览器缓存分为:强缓存和协商缓存。
强缓存和协商缓存并不是平行关系,协商缓存是强缓存的基础上增强的缓存功能。

强缓存的过程:
第一次请求:浏览器第一次发送请求到服务器,服务器会把response header里加上Expires和Cache-Control:max-age=365000000,这两个请求头中的一个或两个。
然后:浏览器收到响应后,会把这个response header以及响应的资源一起缓存下来。

下一次请求时:浏览器根据这两个请求头的值计算当前时间这个缓存是否过期,如果不过期就直接响应缓存内容而不用向服务器发送请求获取资源。

(Expires,它的值是GMT格式的过期的绝对时间,例如是2019年的6月23日 12:00:00 过期,这样等客户端的时间过了这个时间,这个缓存就会过期。Cache-Control:max-age=365000000,这个请求头的max-age的值是一个时间段,也就是说,它保存的是相对时间,每次请求时,浏览器会用客户端时间减去第一次请求时的时间,大于这个相对时间段,则过期,需要重新请求资源)

协商缓存的过程:
第一次请求:浏览器第一次发送请求到服务器,服务器除了会把response header里加上强缓存的配置项(Expires|Cache-Control),还会把协商缓存的配置项加入(Last-Modified|ETag)(Last-Modified是资源最后一次更新的时间。ETag这个header是服务器根据当前请求的资源生成的一个唯一标识,这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改时间没有关系)
然后:浏览器收到响应后,会把这个response header以及响应的资源一起缓存下来。

下一次请求时:浏览器会先判断强缓存是否过期,如果没过期,直接使用缓存资源,过期了则会向服务器发送请求资源,这时的request header里浏览器会加上If-Modified-Since或If-None-Match (If-Modified-Since的值就是上一次请求时返回的Last-Modified的值。If-None-Match的值就是上一次请求时返回的ETag的值)
服务器再次收到资源请求时:

If-Modified-Since: 服务器根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,因为既然资源没有变化,那么Last-Modified也就不会改变。

If-None-Match: 服务器根据浏览器传过来If-None-Match和然后再根据资源生成一个新的ETag,如果这两个值相同就说明资源没有变化,否则就是有变化;如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化
浏览器收到304 Not Modified的响应:表示资源没有变化,缓存资源还可以使用。
下图是流程图:

clipboard.png

二、cookie

Cookie(或者Cookies),指一般网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。cookie一般通过http请求中在头部一起发送到服务器端。一条cookie记录主要由键、值、域、过期时间、大小组成,一般用户保存用户的认证信息。
下面是cookies的常用接口:

var setCookie=function (c_name, value, expiredays, path){
    var exdate=new Date();
    exdate.setDate(exdate.getDate() + expiredays);
    document.cookie=c_name+ "=" + escape(value) + ((expiredays==null) ? "" : ";expires="+exdate.toGMTString()) + ((path==null) ? "" : ";path="+path);
}
var getCookie=function (c_name){
    if (document.cookie.length>0){  //先查询cookie是否为空,为空就return ""
        c_start=document.cookie.indexOf(c_name + "=")  //通过String对象的indexOf()来检查这个cookie是否存在,不存在就为 -1  
        if (c_start!=-1){
            c_start=c_start + c_name.length+1  //最后这个+1其实就是表示"="号啦,这样就获取到了cookie值的开始位置
            c_end=document.cookie.indexOf(";",c_start)  //其实我刚看见indexOf()第二个参数的时候猛然有点晕,后来想起来表示指定的开始索引的位置...这句是为了得到值的结束位置。因为需要考虑是否是最后一项,所以通过";"号是否存在来判断
            if (c_end==-1) c_end=document.cookie.length
            return unescape(document.cookie.substring(c_start,c_end))  //通过substring()得到了值。想了解unescape()得先知道escape()是做什么的,都是很重要的基础,想了解的可以搜索下,在文章结尾处也会进行讲解cookie编码细节
        }
    }
    return ""
}

下面是身份认证相关的:

Cookie Auth
Cookie认证机制就是为一次请求认证在服务端创建一个Session对象,同时在客户端的浏览器端创建了一个Cookie对象;通过客户端带上来Cookie对象来与服务器端的session对象匹配来实现状态管理的。默认的,当我们关闭浏览器的时候,cookie会被删除。但可以通过修改cookie 的expire time使cookie在一定时间内有效
Token Auth:

clipboard.png

Token Auth的优点

Token机制相对于Cookie机制又有什么好处呢?

  • 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.
  • 无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.
  • 更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),而你的服务端只要提供API即可.
  • 去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.
  • 更适用于移动应用: 当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
  • CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。
  • 性能: 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析要费时得多.

三、local storage

localStorage是html5的一种新的本地缓存方案,目前用的比较多,一般用来存储ajax返回的数据,加快下次页面打开时的渲染速度。没有过期时间设置。一般可以在里面存一个时间戳,每次从里面取出这个时间进行人工判断是否过期。

API:
localStorage.setItem()
localStorage.getItem()
localStorage.removeItem()
localStorage.clear()

四、session storage

sessionStorage属性允许你访问一个session storage对象。它与localStorage相似,不同之处在于localStorage里面存储的数据没有过期时间设置,而存储在sessionStorage里的数据会在页面会话结束时被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。在新标签或窗口打开一个页面会初始化一个新的会话,这点和session cookies的运行方式不同。
应该注意的是:无论是sessionStorage还是localStorage中保存的数据都仅限于该页面的协议,简单来说就是不允许跨域。
语法:

// 保存数据到sessionStorage
sessionStorage.setItem('key', 'value');

// 从sessionStorage获取数据
var data = sessionStorage.getItem('key');

// 从sessionStorage删除保存的数据
sessionStorage.removeItem('key');

// 从sessionStorage删除所有保存的数据
sessionStorage.clear();

参考链接:
九种浏览器端缓存机制知多少
浏览器缓存知识小结及应用
浏览器缓存机制剖析


陈凤娟
171 声望17 粉丝

一个追求专业与卓越的前端开发工程师