前言浏览器本地存储,是每一个前端小伙伴都相当熟悉的知识点 。
目前使用率最高的当之无愧为Web Storage API?,也就是localStorage和sessionStorage?,API简单,读取效率高 。然后是indexedDB?,但大部分时间是存在于八股文和面试题中 。indexedDB?的优势为存储空间大,且支持各种数据结构,性能也没有问题 。之所以不为重用,是因为indexedDB?的API多、长且纷杂 。另外,前端使用数据库还需要了解一些表、游标、事务等一些概念,对于不了解后端的同学来说上手成本也就高出localStorage?太多 。所以,在5M内的存储领域,indexedDB?并非首选 。另外WebSQL?已被H5标准放弃,而元老级的Cookie也不再适合现代的客户端存储任务 。
那么有没有一个既保留indexedDB?优点,上手又简单的方法呢,答案就是封装js库,localforage就是一个比较成熟的方案 。
localforage简介localforage是一个 JAVAScript 库,通过简单类似 localStorage API 的异步存储来改进你的 Web 应用程序的离线体验 。它能存储多种类型的数据,而不仅仅是字符串 。
localforage?采用优雅降级策略,若浏览器不支持indexedDB? 或 WebSQL?,则使用 localStorage? 。所以,在优先选用indexedDB存储的前提下,兼容性也得以保证,在所有主流浏览器中都可使用:Chrome,Firefox,IE 和 Safari(包括 Safari Mobile) 。
localforage在github上拥有21.5k个star,npm下载量每周200w左右,正常使用也不会出现问题 。
用法详细的使用方法不做过多赘述,只讲一下存取示例 。
- setItem
// 通过 localForage 完成存储localforage.setItem('key', 'value').then(doSomethingElse); // localForage 同样支持回调函数 localforage.setItem('key', 'value', doSomethingElse);
- getItem
localforage.getItem('somekey').then(function(value) {// 当离线仓库中的值被载入时,此处代码运行console.log(value); }).catch(function(err) {// 当出错时,此处代码运行console.log(err); }); // 回调版本: localforage.getItem('somekey', function(err, value) {// 当离线仓库中的值被载入时,此处代码运行console.log(value); });
实践在一次的业务需求中,基于以下两点,果断选择了localforage 。- 后期会有大量数据需要本地存储 。
- 转转内部有基于localforage.js二次封装的库,且包含设置过期时间的方法,适用于此次需求 。
问题处理艰难复现起初怀疑是localforage?有兼容性问题,但是localforage?有优雅降级机制 。再加上报错内容为QuotaExceededError?,所以在阅读大量资料后基本锁定为在indexedDB的使用上出现了问题 。另外,报错用户数量为个位数,说明了是用户操作或手机存在异常导致的问题 。
在确定了问题的大体方向,排查代码没有思路的前提下,眼前能做的就是复现这个问题 。
刚才提到,QuotaExceededError为内存溢出类型报错,直觉告诉我,需要找一个内存空间剩余最少的测试机,但当时最少的也剩余20GB,于是下载了一天大型软件后,终于在内存剩余100MB左右时成功复现 。
问题原因不同于浏览器会为localStorage?预留5MB左右的储存空间,indexedDB的配额是动态计算的,准确的说是浏览器的储存配额是动态计算的,虽然浏览器实现各不相同,但可用存储量通常取决于设备上可用的存储量 。
这个可用的存储量称为全局限制,Firefox大约为可用磁盘空间的50%,Chrome的这一数据能达到80% 。如果超过此范围,则会发起称为源回收的过程,删除整个源的数据,直到存储量再次低于限制 。删除源数据没有只删一部分的说法——因为这样可能会导致不一致的问题 。
除全局限制外,还有另一个限制称为组限制——为全局限制的20% 。这里可以把每个二级域名看作一组,每组可以聚合使用最多20%的全局限制 。
如果超出组限制,或者源回收过程无法释放足够空间,indexedDB? 或缓存 API就会抛出名为 QuotaExceededError? 的 DOMError 。
如何查看有多少可用存储空间?
【聊聊前端存储库Localforage和存储配额】
if (navigator.storage && navigator.storage.estimate) {const quota = await navigator.storage.estimate();// quota.usage -> 已使用的字节数 。// quota.quota -> 可用最大字节数 。const percentageUsed = (quota.usage / quota.quota) * 100;console.log(`已使用${percentageUsed}%可用储存 。`);const remaining = quota.quota - quota.usage;console.log(`最多可再写入${remaining}字节 。`); }
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 溴氢酸、碘氢酸应避光存储?氢溴酸化学式?
- 前端js中http跳转https报403错误,请求头referer详解
- Node.js 应用全链路追踪技术——全链路信息存储
- 大前端领域 infoq 前端
- 为什么 JavaScript 在国外逐渐用于前端+后端开发,而国内还是只用它做前端?
- 分享9个前端开发人员必备的查询手册工具网站
- object JavaScript选择 map而非对象存储键值对的 5 个理由附示例
- 想找个人聊聊天都挺难的 找人聊天
- ps切片工具的使用,存储为web格式 存储为web所用格式
- 关于前端产品职业发展分析 前端转产品经理工作