localstorage超出存储限制的时候会发生什么?

1,590 阅读4分钟

我们都知道localstorage的大小是5M左右,一般情况也不会在loacl里面存储高于5M的内容,也不太清楚如果超出5M会发生什么?上个月就发生了真实案例让我了解了到底会发生什么。

公司的发生一起p0bug,就是因为用户本地的loacl超出存储限制导致的,因为这个项目大致是从电商刚刚兴起时搭建的,已经过了快10年的时间,散落了10年间各不相同的逻辑,local也在不停的使用,终于有一天用户这边的loacl爆仓了,导致有些功能失效了,就是因为loacl只取不存了。

localStorage 超出存储限制时,尝试存入新数据会触发 QuotaExceededError 异常,并且数据不会被写入。

具体行为

  1. 存储超限

    • localStorage.setItem(key, value) 触发 QuotaExceededError 异常,写入失败。
    • 旧数据不会被自动删除,新数据不会存进去。
  2. 读取数据

    • localStorage.getItem(key) 仍然可以正常读取已存储的数据,不会报错。
  3. 删除数据

    • 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 字节)。不同浏览器的限制大致如下:

浏览器约定大小
Chrome10MB
Firefox10MB
Safari5MB
Edge10MB
IE10MB
移动端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。