Cookie和Web缓存机制

本周阅读了JS高程的缓存机制部分,对于Cookie和Web缓存机制有了更深的了解,今年二三月份参加实习生电面多次被问到Cookie以及LocalStorage、SessionStorage的区别,当时对于每一部分都有个大致的了解,且没有实际运用,所以趁这次机会,也动手实现了一把,写下这篇博客以整理思路。

缓存机制对于用户访问网页来说是很方便的。如果将用户名,偏好设定或者其他一些数据存储到客户端,而不必每次访问网页都输入数据,可能对于用户体验会更好。常用的缓存机制有Cookie和Web缓存机制这两大类。

Cookie机制

Cookie应该算是HTTP里面的一个概念。关于HTTP协议,我会在HTTP模块整理一篇博客详细介绍,这里先做简单说明:在客户端请求服务端数据的时候,会发送一个HTTP请求,这个HTTP请求有头部信息,还有HTTP数据报文等等,服务端在接收到客户端的HTTP请求之后,会进行一些操作,然后发送一个HTTP响应给客户端,这个响应也包含头部信息和数据报文。响应头部里面会包含HTTP状态码,表示响应是否成功。如果不成功,其原因是什麽。
而加入Cookie的过程又是怎么样的?看下图:
这里写图片描述
- 首先,当客户端第一次访问服务器时,先发送HTTP请求给服务端;
- 服务端在收到客户端发来的HTTP请求之后,会在本服务器上做一些操作,操作结束会根据结果发一个HTTP响应给客户端。这时候,会在HTTP响应报文的头部中加入:Set-Cookie: name = value,并把该信息存储到本服务器上(Session);
- 客户端收到HTTP响应报文之后,会检查Set-Cookie字段,并将其值存储到浏览器中。当客户端第二次再去访问该服务器时,会将之前保存的信息取出来并在HTTP请求头部加上一个Cookie:name = value
- 这时候服务器收到HTTP请求报文之后,将Cookie取出来,与服务器存储的Session进行匹配,如果匹配上,用户信息验证成功。

Cookie限制

Cookie是保存在客户端磁盘上的,所以不宜占据太多磁盘空间。同时,Cookie是绑定在特定域名上的。当设定了一个Cookie之后,再给创建它的域名发一个请求时,还会包含该Cookie。所以对Cookie的限制是对每个域来说的。但各个浏览器也有不同:
IE6及以下每个域名最多包含20个Cookie;
IE7及以上每个域名最多50个Cookie;
Firefox每个域名最多50个Cookie;
Opera下每个域名最多30个Cookie;
Sarafi和Chrome对每个域的Cookie数目没有严格限制。

每个Cookie最大是4096B(加减一)。即对于大多数浏览器来说,Cookie大小是4096个字节,而对于少数浏览器,有的是4097B,而有的是4095B.因此为了浏览器兼容性,最好将Cookie大小限制在4095B之内。

Cookie是什么形式的

Cookie有名称,值,过期时间,域,路径,安全标志这几个部分。
比如:
Set-Cookie: name=”Liu”;expires:Mon, 29-05-2017 00:00:00 GTM;domain=”baidu.com”;path=/;secure
上面这个形式设置了一个名称为name的Cookie,它的值为”Liu”,到2017年5月29的凌晨过期,对于baidu.com和www.baidu.com及其子域都有效,并且该cookie是安全的,这意味着只能通过SSL连接(如https)来发送,而仅仅用http协议是不能发送的。

Cookie与JavaScript

Cookie也可以利用JavaScript来操作。只不过涉及到一些字符串解析等一些比较繁琐的过程。我们可以通过document.cookie来读取或者设置Cookie。

document.cookie = "age=20";

这里写图片描述

打开浏览器进行调试,可以看到在Application中的Cookies选项中,有了名称为age,值为20的cookie.
需要注意的一点是:直接在本机利用JS去设置cookie是没有用的,因为你要设置cookie 服务器必须发一个set-cookie,所以需要启一个服务器。

上面是设置简单cookie的方式,下面介绍设置和获取cookie复杂的方式,或者说通用方法。
我们可以把设置Cookie和获取Cookie封装到一个对象中,然后通过对象去调它的方法。并且要知道cookie的结果,类似于下面这样:
name=”Liu”;expires=”05-05-2017 00:00:00 GTM;path=/;secure”

var UtilC = {
    get : function(cname){
        var cookieName = cname + "=";
        var CStart = document.cookie.indexOf(cookieName);
        //找到要获取的cookie名在document.cookie中的位置
        if(CStart != -1)
        {
            var CEnd = document.cookie.indexOf(";", CStart);//判断该cookie是否被设置了多个选项
            if(CEnd == -1) 
            {
            //若从该cookie选项之后只有一个选项,直接返回'='后到末尾的字符串
                return document.cookie.substring( CStart + cookieName.length);
            }
            else
            {
            //若该选项之后设置了多个选项,则返回'='之后';'之前的字符串
                return document.cookie.substring( CStart + cookieName.length, CEnd);
            }
        }
        else
            return false;  //若在document.cookie中没有找到要获取的cookie名,返回false
    },
    set : function(name, value, expires, path, domain, secure){
    //设置cookie时对于中文的字符必须要编码
            var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);
            if(expires instanceof Date)
            {
                cookieText += ";expires=" + expires.toGMTString();
            }
            if(path)
            {
                cookieText += ";path=" + path;
            }
            if(domain)
            {
                cookieText += ";domain=" + domain;
            }
            if(secure)
            {
                cookieText += ";secure";
            }
        document.cookie = cookieText;
    },
    removeCookie: function(name){
    //删除cookie时将其过期时间设为过去的一个时间就可以了
        this.set(name, '', new Date(0));
    }
}

UtilC.set('name', 'Hellen'); 
console.log(UtilC.get("name"));    //输出Hellen 

当调用下面代码之后

UtilC.set('name', 'Hellen');

浏览器调试窗口中的Application如下图所示:
这里写图片描述
可以看到名为name,值为Hellen的cookie被清除了。

子Cookie

由于cookie的个数以及大小限制,出现了子cookie,它相当于cookie的一小段,格式可能类似下面这样:
name=name1=”Liu”&name2=”Yang”&name3=”Chen”
这就是一个名为name的cookie,但是它又有3个子cookie。
同样也可以利用JS写一个设置cookie或获取cookie的通用方法,但是主要这时设置可以设置某个cookie选项,也可以设置某个cookie 选项中某一个子cookie的值。看代码:

var UtilCookie = {
    get : function(Cname, name){
        var data = this.getAllCookie(Cname);
        if(data[name])
            return data[name];
        else
            return false;
   },
   getAllCookie : function(cookieName){
       cookieName = cookieName + "=";
       var res = {};
       var CStart = document.cookie.indexOf(cookieName);
       if(CStart != -1)
       {
           var CEnd = document.cookie.indexOf(";", CStart);
           if(CEnd == -1)
           {
                CStartStr = document.cookie.substring( CStart + cookieName.length);
                var part = CStartStr.split("&");
                for(var i = 0; i < part.length; i++)
                {
                    var partP = part[i].split("=");
                    res[partP[0]] = partP[1];
                }

            }
            else
            {
                CStartStr = document.cookie.substring( CStart + cookieName.length, CEnd);
                var part = CStartStr.split("&");
                for(var i = 0; i < part.length; i++)
                {
                    var partP = part[i].split("=");
                    res[partP[0]] = partP[1];
                }
            }
            return res;
        }
        else
        {
            return false;
        }

    },
    setAll: function(Cname, subcookie, expires, path, domain, secure){
        var CText = encodeURIComponent(Cname) + "=";
        var Arr = [];
        for(subName in subcookie)
        {
            if(subName.length > 0 && subcookie.hasOwnProperty(subName))
            {
                Arr.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookie[subName]));
            }
        }
        if(Arr.length > 0)
        {
            CText += Arr.join("&");
        }
        if(expires instanceof Date)
        {
            CText += ";expires=" + expires.toGMTString();
        }
        if(path)
        {
            CText += ";path=" + path;
        }
        if(domain)
        {
            CText += ";domain=" + domain;
        }
        if(secure)
        {
            CText += ";secure";
        }
        document.cookie = CText;
    },
    set : function(name, subName, value, expires, domain, path, secure){
        var subcookie = this.getAllCookie(name);
        subcookie[subName] = value;
        this.setAll(name, subcookie, expires, path, domain, secure);
    }
}
//子cookie的格式: name=name1="Liu"&name2="Hellen"&name3="Yang";

UtilCookie.setAll( "name", { name1:"Liu", name2:"Yang", family:"YL" });
UtilCookie.get("name", "name1");

此时,浏览器的Application中就可以看到设置的cookie了。
这里写图片描述

Web缓存机制

Web 缓存的出现主要是为了弥补cookie带来的一些局限,当数据严格控制在客户端时,可以不用通过HTTP来持续得将数据发给服务器。

主要使用比较多的就是sessionStorage和localStorage,这两种都是Storage类型,Web Storage提供一个Storage类型,它有下面这么写方法:
getItem(item);
setItem(item, value)
removeItem(item)
所以sessionStorage和localStorage都可以调用上面的方法。

SessionStorage

sessionStorage.setItem("Age", 20);

浏览器中就可以看到Session Storage中有Age这个缓存
这里写图片描述
当关闭该页面,重新访问时(没有了设置sessionStorage),此时在Application里的SessionStorage并没找到Age这个缓存,说明Session Storage是基于会话的,也就是说当前页面关闭之后,session Storage就消失了。
localStorage

localStorage.setItem("Age", 20);

这里写图片描述
当浏览器关闭,重新打开时,看到localStorage中还有Age这个缓存,因此localStorage是永久缓存的,除非手动清除,否则它会一直存在,上图中的musics,searchHistory等等正说明了这一点。
清除localStorage可以调Storage类型的接口:

localStorage.removeItem("Age");

以上是我这次关于缓存机制的总结和分享,希望大家可以共同讨论和进步!

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值