mengtuifrontend / Blog

芦叶满汀洲,寒沙带浅流。二十年重过南楼。柳下系船犹未稳,能几日,又中秋。 黄鹤断矶头,故人今在否?旧江山浑是新愁。欲买桂花同载酒,终不似,少年游。
18 stars 5 forks source link

本地存储方案介绍 —— 现有方案 #5

Open mengtuifrontend opened 5 years ago

mengtuifrontend commented 5 years ago

本地存储方案介绍 —— 现有方案

文章将从 LocalStorage 开始讲起,聊到 localForage,在后续的篇章中将会说一说新的存储方案。

本地存储功能在我们站点应用中十分常见,LocalStorageSessionStorage 等都是大家经常使用的。然后目前也有很多应用选择避免使用 LS、SS,而改用基于本地数据库(indexedDB, WebSQL 之类)的解决方案,这是为什么呢?

为什么好好的,大家都不使用 LocalStorage/SessionStorage 了?

LS 的弊端

LS 一推出就以其简单的 API 大受欢迎。基于 storage 规范(嗯,这个不是 HTML5 的内容),LS 拥有十分简单的 API:

localStorage.setItem( 'key', 'value' )
localStorage.getItem( 'key' ) // ===> 'value'

不得不说 LS 给开发者带来的很多好处:

随着 LS 被广泛地使用,它的弊端也慢慢为人所熟知:

糟糕的性能问题

LS 本质上是一种同步的行为,这意味着它在执行时会阻塞渲染,影响你的应用的体验。

每次 LS 执行文件 IO 都意味着对本地硬盘的操作,这可能会需要很多的时间,具体取决于系统执行的操作。而且,为了显得流畅,应用在加载时会等待 LS 内容加载至内存中,这意味着 LS 使用的越多,应用加载就越慢。

SSL 隔离

LS 遵循规范中基于 Scheme、hostname、unique port 的三者隔离特性。但是由于 LS 是明文存储,在安全页面和非安全页面中都不应该将敏感数据存储于 LS,所以 HTTPHTTPS 的站点本应该可以同享 LS 内容,但是实际上却并非如此。

隐私模式数据丢失

LS 在隐私模式下会使用一个新的临时数据库,这意味着在隐私模式被关闭后,LS 的数据也将丢失。

存储限制

LS 的存储限制一般仅 5Mb 左右,并没有太好的解决方案进行 LS 的扩容。

值转义

LS 存储值的过程中会自行将非字符串类型值转义成字符串,是一个容易被人忽略的问题,比如:

localStorage.setItem( 'key', 900 )
localStorage.getItem( 'key' ) === 900 // false, return '900'

localStorage.setItem( 'key', {toString: function () {return '100'}} )
localStorage.getItem( 'key' ) === '100' // true

总之,大家都开始寻找更好的存储方案进行替代原来的 LS。

localForage

localForage 是一个快速的简单的 JS 存储工具。他使用的是异步存储(基于 IndexedDB 或者 WebSQL),并且它有一套类似 LS 的 API。

访问 localForage

localForage 的优势

API 简单

localforage.setItem('key', 'value', function (err) {
  // if err is non-null, we got an error
  localforage.getItem('key', function (err, value) {
    // if err is non-null, we got an error. otherwise, value is the value
  });
});

Callback 和 Promise

由于 localForage 使用的是异步存储,所以提供的 API 是异步 API,localForage 同时提供了 Callback(Node-style,即回调第一个参数为 error) 和 Promise 的方式进行异步处理。

localforage.setItem('key', 'value', function (err) {
  // if err is non-null, we got an error
  localforage.getItem('key', function (err, value) {
    // if err is non-null, we got an error. otherwise, value is the value
  });
});

////

localforage.setItem('key', 'value').then(function () {
  return localforage.getItem('key');
}).then(function (value) {
  // we got our value
}).catch(function (err) {
  // we got an error
});

存储值类型丰富

localForage 可以存储包括 BlobsTypedArrays 和其他 JS 对象:

多实例并存

LS 无法同时存储同 key 的多个值,localForage 可以通过实例化加以解决。

var store = localforage.createInstance({
  name: "nameHere"
});

var otherStore = localforage.createInstance({
  name: "otherName"
});

// Setting the key on one of these doesn't affect the other.
store.setItem("key", "value");
otherStore.setItem("key", "value2");

另外,由于 localforage 是基于 indexedDB 这类本地数据库的,所以没有存储限制,或者说在硬盘空间足够的情况下是不存在存储限制的。localforage 在数据存储的容量方面完胜 LS。


Thanks