关于cookie:一文搞懂CookieStorageIndexedDB

关注公众号“执鸢者”,回复“材料”获取500G材料(各“兵种”均有),还有业余交换群等你一起来洒脱。(哈哈)

随着前端技术的倒退,存储变的越来越重要,就目前来看,浏览器次要反对三类存储:Cookie、Storage、IndexedDB,上面别离介绍这三类存储形式。

一、Cookie

1.1 定义

Cookie是一个保留在浏览器中的简略的文本文件,该文件与特定的Web文档关联在一起,保留了该浏览器拜访这个Web文档时的信息,当浏览器再次拜访这个Web文档时这些信息可供该文档应用。(HTTP是无状态的协定,即HTTP协定自身不对申请和响应之间的通信状态进行保留,为了实现冀望的保留状态性能,引入了cookie技术)

1.2 Cookie组成

在理解Cookie组成之前先理解一下Cookie的整个申请流程,这个流程分为类:一类是没有Cookie信息状态下的申请,另一类是存有Cookie状态下的申请。

通过下面的流程图能够看出,Cookie是在服务端生成的,通过查问材料理解到其是在从服务端发送的响应报文内的一个叫做Set-Cookie的首部字段信息,响应报文中有该首部字段则告诉客户端保留Cookie,则Cookie的组成则跟Set-Cookie能够设置哪些值相干,目前次要有以下几类:

  1. NAME=VALUE

Cookie的名称和值,其中NAME是惟一标识cookie的名称,不辨别大小写;VALUE是存储在Cookie里的字符串值,该值必须通过URL编码。

  1. Domain=域名

Cookie无效的域,发送到这个域的所有申请都会蕴含对应的Cookie。(若不指定则默认为创立Cookie的服务器的域名)

  1. Path=PATH

申请URL中蕴含这个门路才会把Cookie发送到服务器(若不指定则默认为文档所在的文件目录)

  1. Expires=DATE

Cookie的有效期,默认状况下,浏览器会话完结后会删除所有cookie。

  1. Secure

设置后仅在HTTPS平安通信时才会发送Cookie

  1. HttpOnly

设置后只能在服务器上读取,不能再通过JavaScript读取Cookie

const express = require('express');

const app = express();

app.get('/', (req, res) => {
    res.cookie('myCookie', 'myCookie', {
        expires: new Date(Date.now() + 900000),
        secure: true,
        httpOnly: true
    });
    res.send('get申请曾经被解决');
})
app.listen(8090, () => {
    console.log('8090端口曾经启动!!!');
});

通过申请 http://127/.0.0.1:8090 来看看其后果:

  1. 第一次返回的Cookie后果

  1. 后续申请所带的Cookie信息

1.3 Cookie特点

  1. 每个Cookie不超过4096字节;
  2. 每个域中Cookie个数有限度,就拿最新版来说:IE和Edge不超过50个;Firefox不超过150个;Opera不超过180个;Safari和Chrome没有限度;
  3. Cookie超过单个域的下限,浏览器会删除之前设置的Cookie;
  4. 创立的Cookie超过最大限度,该Cookie会被静默删除;
  5. 可设置生效工夫,没有设置则会话完结会删除Cookie;
  6. 每个申请均会携带Cookie,若Cookie过去会带来性能问题;
  7. 受同源策略限度

1.4 Cookie的操作

Cookie存储到浏览器端之后依然能够对其进行读、写、删除,因为js对Cookie操作的反对并不是很敌对,所以须要进行一些简略的封装。

class CookieUtil {
    // 获取Cookie中的对应属性
    static get(name) {
        const cookies = document.cookie;
        const cookiesArr = cookies.split(';');
        for (let index = 0; index < cookiesArr.length; index++) {
            const presentCookieArr = cookiesArr[index].split('=');
            if (presentCookieArr[0] === name) {
                return presentCookieArr[1];
            }
        }

        return null;
    }

    // 设置对应的Cookie值
    static set(name, value, expires, path, domain, secure) {
        let cookieText = `${name}=${value}`;
        if (expires instanceof Date) {
            cookieText += `; expire=${expires.toGMTString()}`;
        }
        if (path) {
            cookieText += `; path=${path}`;
        }
        if (domain) {
            cookieText += `; domain=${domain}`;
        }
        if (secure) {
            cookieText += `; secure`;
        }
        document.cookie = cookieText;
    }

    // 删除对应的Cookie
    static deleteCookie(name) {
        CookieUtil.set(name, '', new Date(0));
    }
}

二、Web Storage

Web Storage的目标是解决通过客户端存储不须要频繁发送回服务器的数据时应用cookie的问题,其提供了cookie之外的存储会话数据的路径和跨会话长久化存储大量数据的机制,其次要有两个对象:localStorage和sessionStorage,localStorage是永恒存储机制,sessionStorage是跨会话的存储机制。

2.1 sessionStorage

sessionStorage是跨会话的存储机制,具备以下特点:

  1. sessionStorage对象值存储会话数据,其生命周期会存储到浏览器敞开。(在该过程中刷新页面其数据不受影响)
  2. 浏览器在实现存储写入时应用同步阻塞形式,数据会被立刻提交到存储。
  3. 独立关上同一个窗口同一个页面或一个Tab,sessionStorage也是不一样的。
  4. 存储空间大小限度为每个源不超过5M。
// 应用办法存储数据
sessionStorage.setItem('sessionName1', 'value1');
// 应用属性存储数据
sessionStorage.sessionName2 = 'value2';

// 应用办法获得数据
const sessionValue1 = sessionStorage.getItem('sessionName1');
console.log('sessionValue1的值为:', sessionValue1);
// 应用属性获得数据
const sessionValue2 = sessionStorage.sessionName2;
console.log('sessionValue2的值为:', sessionValue2);

// 循环遍历sessionStarage
for (let index = 0; index < sessionStorage.length; index++) {
    // 应用key()办法取得指定索引处的名称
    const key = sessionStorage.key(index);
    const value = sessionStorage.getItem(key);
    console.log('循环遍历后果:', key, value);
}

// 应用办法删除值
sessionStorage.removeItem('sessionName1');
// 应用delete删除值
delete sessionStorage.sessionName2;

// 应用clear()办法清空sessionStorage
sessionStorage.clear();

2.2 localStorage

localStorage是永恒存储机制,具备以下特点:

  1. 生命周期是永恒的,除非被革除,否则永恒保留。
  2. 存储空间大小限度为每个源不超过5M。
  3. 受同源策略限度。
  4. 浏览器存储时采纳同步存储形式。
// 应用办法存储数据
localStorage.setItem('localName1', 'value1');
// 应用属性存储数据
localStorage.localName2 = 'value2';

// 应用办法获得数据
const localValue1 = localStorage.getItem('localName1');
console.log('localValue1的值为:', localValue1);
// 应用属性获得数据
const localValue2 = localStorage.localName2;
console.log('localValue2的值为:', localValue2);

// 循环遍历localStarage
for (let index = 0; index < localStorage.length; index++) {
    // 应用key()办法取得指定索引处的名称
    const key = localStorage.key(index);
    const value = localStorage.getItem(key);
    console.log('循环遍历后果:', key, value);
}

// 应用办法删除值
localStorage.removeItem('localName1');
// 应用delete删除值
delete localStorage.localName2;

// 应用clear()办法清空localStorage
localStorage.clear();

三、IndexedDB

3.1 IndexedDB整个构造


对于整个IndexedDB为上述图中所示:

  1. 一个域名下能够蕴含多个数据库;
  2. 一个数据库中蕴含多个对象仓库,就相似与Mysql一个库中有多张表一样。
  3. 每个对象仓库中蕴含多条数据记录。

3.2 次要特点

IndexedDB是浏览器中存储结构化数据的一个计划,其设计简直是齐全异步的,次要有以下特点:

  1. 键值对存储

在对象仓库中,数据以“键值对”模式保留,每个数据记录都有举世无双的主键。

  1. 异步

IndexedDB操作时不会锁死浏览器,用户仍然能够进行其它操作。

  1. 反对事务

一些列操作步骤之中只有有一步失败,整个事务就都勾销,数据库回滚到事务产生之前的状态,不存在只改写一部分数据的状况。

  1. 受同源策略限度

只能拜访本身域名下的数据库,不能跨域拜访数据库。

  1. 存储空间大

每个源都有存储空间的限度,而且这个限度跟浏览器无关,例如Firefox限度每个源50MB,Chrome为5MB。

  1. 反对二进制存储

不仅能够存储字符串,还能够存储二进制数据(ArrayBuffer和Blob)

3.3 数据库操作

IndexedDB像很多其它数据库一样有很多操作,上面就通过实战的形式一起理解这些操作。

3.3.1 初始化数据库

第一步是初始化数据库,传入创立的数据库名和版本,获取对应的数据库操作实例。

class IndexedDBOperation {
  constructor(databaseName, version) {
      this.atabaseName = databaseName;
      this.version = version;
      this.request = null;
      this.db = null;
  }

  // 数据库初始化操作
  init() {
      this.request = window.indexedDB.open(this.databaseName, this.version);
      return new Promise((resolve, reject) => {
          this.request.onsuccess = event => {
              this.db = event.target.result;
              console.log('数据库关上胜利');
              resolve('success');
          };
          this.request.onerror = event => {
              console.log('数据库关上报错');
              reject('error');
          };
          this.request.onupgradeneeded = event =>{
              this.db = event.target.result;
              console.log('数据库降级');
              resolve('upgradeneeded');
          };
      });
  }
}

3.3.2 对象仓库操作

数据是在对象仓库中存储的,创立好数据库后则须要创立所需的数据仓库

class IndexedDBOperation {
  // ……
  // 创立数据仓库
  createObjectStore(objectStoreName, options) {
      let objectStore = null;
      if (!this.db.objectStoreNames.contains(objectStoreName)) {
          objectStore = this.db.createObjectStore(objectStoreName, options);
      }
      return objectStore;
  }
}

3.3.3 数据操作

不论是关系型数据库还是非关系型数据库,CURD必定是必不可少的,谁让咱们是“CURD工程师”呢!!!

class IndexedDBOperation {
  // ……
  // 新增内容
  add(objectStore, content) {
      objectStore.add(content);
  }
  
  // 获取内容
  get(objectStore, id) {
      const request = objectStore.get(id);
      return new Promise((resolve, reject) => {
          request.onsuccess = resolve;
          request.onerror = reject;
      });
  }
  
  // 更新内容
  update(objectStore, content) {
      const request = objectStore.put(content);
      request.onsuccess = event => {
          console.log('更新胜利');
      };
      request.onerror = event => {
          console.log('更新失败');
      };
  }
  
  // 删除内容
  remove(objectStore, deleteId) {
      const request = objectStore.delete(deleteId);
      request.onsuccess = event => {
          console.log('删除胜利');
      };
      request.onerror = event => {
          console.log('删除失败');
      };
  }
}

3.3.4 遍历内容

提到IndexedDB数据库,不得不提其的游标操作。

class IndexedDBOperation {
  // ……
  // 打印全副数据
  printAllDataByCursor(objectStore) {
      const cursorRequest = objectStore.openCursor();
      cursorRequest.onsuccess = event => {
          const cursor = event.target.result;
          if (cursor) {
              console.log(`利用游标打印的内容,id为${cursor.key}, 值为${cursor.value}`);
              // 挪动到下一条记录
              cursor.continue();
          }
      };
  }
}

3.3.5 调用代码

下面写了一个数据库的类,然而依然不晓得怎么调用呀,上面就用一个demo讲述其调用。

const indexedDBOperation = new IndexedDBOperation('dbName1', 1);
indexedDBOperation
.init()
.then(type => {
    const objectStoreName = 'testObjectStore';
    if (type === 'upgradeneeded') {
        indexedDBOperation.createObjectStore(objectStoreName, {
            keyPath: 'id'
        });
    }
    const transaction = indexedDBOperation.db.transaction([objectStoreName], 'readwrite');
    const objectStore = transaction.objectStore(objectStoreName);

    indexedDBOperation
    .get(objectStore, 1)
    .then(event => {
        if (event.target.result) {
            indexedDBOperation.update(objectStore, {
                id: 1,
                name: '执鸢者+纸鸢'
            });
            console.log('数据库中曾经存在', event.target.result, ',则进行更新操作');
        }
        else {
            indexedDBOperation.add(objectStore, {
                id: 1,
                name: '执鸢者'
            });
            console.log('数据库中不存在,则进行增加');
        }
    })
    .catch(console.log);

    indexedDBOperation.printAllDataByCursor(objectStore);

    transaction.onsuccess = event => {
        console.log('事务操作胜利');
    };
    transaction.onerror = event => {
        console.log('事务操作失败');
    };
    transaction.oncomplete = event => {
        console.log('整个事务胜利实现');
    }
})
.catch(console.log);

参考文献

  1. 浏览器数据库 IndexedDB 入门教程
  2. [javascript高级程序设计4]()
  3. IndexedDB API

1.如果感觉这篇文章还不错,来个分享、点赞吧,让更多的人也看到

2.关注公众号执鸢者,支付学习材料(前端“多兵种”材料),定期为你推送原创深度好文

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理