我们都知道localstorage的大小是5M左右,一般情况也不会在loacl里面存储高于5M的内容,也不太清楚如果超出5M会发生什么?上个月就发生了真实案例让我了解了到底会发生什么。
公司的发生一起p0bug,就是因为用户本地的loacl超出存储限制导致的,因为这个项目大致是从电商刚刚兴起时搭建的,已经过了快10年的时间,散落了10年间各不相同的逻辑,local也在不停的使用,终于有一天用户这边的loacl爆仓了,导致有些功能失效了,就是因为loacl只取不存了。
当 localStorage 超出存储限制时,尝试存入新数据会触发 QuotaExceededError 异常,并且数据不会被写入。
具体行为
-
存储超限
localStorage.setItem(key, value)触发QuotaExceededError异常,写入失败。- 旧数据不会被自动删除,新数据不会存进去。
-
读取数据
localStorage.getItem(key)仍然可以正常读取已存储的数据,不会报错。
-
删除数据
localStorage.removeItem(key)依然可以删除已有数据,从而释放存储空间。
如何避免 QuotaExceededError
-
检查可用空间
navigator.storage.estimate()可以估算已使用和总可用存储量(仅在部分浏览器支持)。js 复制编辑 navigator.storage.estimate().then(({ usage, quota }) => { console.log(`已使用: ${usage} bytes`); console.log(`总可用: ${quota} bytes`); }); -
压缩数据
如果存储的是 JSON 数据,可以使用JSON.stringify()+LZString(LZ压缩算法)进行压缩:js 复制编辑 localStorage.setItem('data', LZString.compress(JSON.stringify(bigData))); -
改用 IndexedDB
IndexedDB允许存储更大数据(通常能达到数百 MB),适合存储结构化数据。 -
监控异常并降级处理
try { localStorage.setItem('key', 'value'); } catch (e) { if (e.name === 'QuotaExceededError') { console.warn('LocalStorage 存储超限,考虑清理数据或改用 IndexedDB'); } }
总结:超出 localStorage 限制时,写入新数据会失败并抛出 QuotaExceededError,但如果已有数据仍然可读。可以使用压缩、删除部分数据或改用 IndexedDB 等方案替代。
所以为了保持功能的可用性,也为了解决这个问题,删除了大量无用的需要存储在local代码,把一些需要经常用到loacl的代码逻辑,例如广告、红点、提示等功能进行改造,但还有些不太好动的,就使用indexDB来存储了,也用indexDB封装了一个新的存储公用方法,尽量少使用loacl来处理业务逻辑了。
知识点
1. localStorage 的存储大小是多少?
localStorage 的存储上限因浏览器而异,通常在 5MB ~ 10MB 之间(以 UTF-16 字符存储,每个字符占 2 字节)。不同浏览器的限制大致如下:
| 浏览器 | 约定大小 |
|---|---|
| Chrome | 10MB |
| Firefox | 10MB |
| Safari | 5MB |
| Edge | 10MB |
| IE | 10MB |
| 移动端 | 2.5MB ~ 10MB |
为什么大小受限?
localStorage存储在 浏览器的缓存(Quota Manager) 中,主要用于轻量级存储,不能滥用。- 不会自动清理(除非用户手动清理缓存或浏览器存储已满)。
2. 为什么使用 IndexedDB 更好?
IndexedDB 是一个基于对象存储的 NoSQL 数据库,优于 localStorage,主要优势如下:
存储容量更大
- localStorage 限制 5MB~10MB,而 IndexedDB 可以存储数百 MB 甚至 2GB+ ,取决于浏览器和设备存储空间。
navigator.storage.estimate()可以查看 IndexedDB 允许的存储空间。
支持复杂数据存储
- localStorage 只能存储字符串,需要手动
JSON.stringify()转换对象。 - IndexedDB 可存储:对象、数组、二进制数据(Blob/File)、甚至整个 JavaScript 对象。
适合大量数据
- localStorage 读写是同步(阻塞主线程) ,如果数据过大,可能导致页面卡顿。
- IndexedDB 采用异步 API,不会影响 UI 交互,适合存储大量数据。
可建立索引,提高查询效率
- localStorage 仅支持
key-value形式存取,查找数据时必须遍历所有键值。 - IndexedDB 支持索引,可以快速查询特定字段的数据,适合大数据量应用。
可事务管理
- localStorage 没有事务机制,可能导致数据不一致。
- IndexedDB 支持事务,可以保证数据的完整性和一致性。
3. 何时用 localStorage?何时用 IndexedDB?
| 需求 | 选择 |
|---|---|
| 存储少量键值对(<5MB) | localStorage |
| 需要快速读写小数据 | localStorage |
| 需要存储大数据(>10MB) | IndexedDB |
| 需要存储 JSON/对象/文件 | IndexedDB |
| 需要快速查询/索引 | IndexedDB |
| 需要事务管理 | IndexedDB |
4. IndexedDB 使用示例
// 打开数据库
const request = indexedDB.open("MyDatabase", 1);
request.onupgradeneeded = function (event) {
const db = event.target.result;
// 创建对象存储(类似表)
const store = db.createObjectStore("users", { keyPath: "id" });
// 创建索引
store.createIndex("name", "name", { unique: false });
};
request.onsuccess = function (event) {
const db = event.target.result;
const transaction = db.transaction(["users"], "readwrite");
const store = transaction.objectStore("users");
// 添加数据
store.add({ id: 1, name: "张三", age: 28 });
// 读取数据
const getRequest = store.get(1);
getRequest.onsuccess = function () {
console.log(getRequest.result);
};
};
5. 结论
- localStorage 适合存储少量数据(小于 5MB),但会阻塞主线程。
- IndexedDB 适合存储大数据,支持对象、索引、事务,并且是异步的,不会影响 UI。
- 如果数据量较大(如 10MB 以上),建议使用 IndexedDB。