IndexedDB:浏览器端的强大数据库

IndexedDB:浏览器端的强大数据库

在现代 Web 开发中,随着应用复杂度的增加,客户端存储的需求也日益增长。现有的存储方案如 Cookie 和 LocalStorage 已经无法满足存储大量数据的需求。这时,IndexedDB 作为一种强大的客户端数据库解决方案应运而生。

一、IndexedDB 简介

IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据。它支持存储包括文件和二进制大型对象(blobs)在内的多种数据类型,并通过索引实现对数据的高性能搜索。与 LocalStorage 相比,IndexedDB 提供了更大的存储空间(通常不少于 250MB,甚至没有上限)和更丰富的功能,如事务支持、异步操作等。

IndexedDB 的主要特点如下:

  • 键值对存储:数据以"键值对"的形式保存,每个数据记录都有一个唯一的主键。
  • 异步操作:操作不会阻塞浏览器,用户可以继续进行其他操作。
  • 事务支持:确保数据操作的原子性,要么全部成功,要么全部失败。
  • 存储空间大:存储空间远大于 LocalStorage。
  • 支持二进制存储:可以存储二进制数据,如图片、文件等。

二、IndexedDB 的重要概念

在使用 IndexedDB 之前,我们需要了解一些基本概念:

  • 数据库:存储数据的容器,每个域名可以创建多个数据库。
  • 对象仓库:类似于关系型数据库中的表,用于存储数据记录。
  • 数据记录:对象仓库中的数据,包含主键和数据体。
  • 索引:加速数据检索的工具,可以为对象仓库中的属性创建索引。
  • 事务:用于执行一系列数据操作的机制,确保操作的原子性。
  • 指针(游标):用于遍历对象仓库中的数据。

三、IndexedDB 的基本操作

(一)操作数据库

1. 打开数据库

使用 indexedDB.open 方法打开数据库。如果数据库不存在,则会创建一个新的数据库。

javascript 复制代码
function openDB(dbName, version = 1) {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open(dbName, version);

        request.onsuccess = function (event) {
            console.log("数据库打开成功");
            resolve(event.target.result);
        };

        request.onerror = function (event) {
            console.error("数据库打开失败");
            reject(event.target.error);
        };

        request.onupgradeneeded = function (event) {
            console.log("数据库升级");
            const db = event.target.result;
            const objectStore = db.createObjectStore("stu", { keyPath: "stuId", autoIncrement: true });
            objectStore.createIndex("stuName", "stuName", { unique: false });
            objectStore.createIndex("stuAge", "stuAge", { unique: false });
        };
    });
}
2. 关闭数据库
javascript 复制代码
function closeDB(db) {
    db.close();
    console.log("数据库已关闭");
}
3. 删除数据库
javascript 复制代码
function deleteDB(dbName) {
    const request = indexedDB.deleteDatabase(dbName);
    request.onsuccess = function () {
        console.log("数据库删除成功");
    };
    request.onerror = function (event) {
        console.error("数据库删除失败", event.target.error);
    };
}

(二)插入数据

javascript 复制代码
function addData(db, storeName, data) {
    const transaction = db.transaction([storeName], "readwrite");
    const objectStore = transaction.objectStore(storeName);
    const request = objectStore.add(data);

    request.onsuccess = function () {
        console.log("数据插入成功");
    };
    request.onerror = function (event) {
        console.error("数据插入失败", event.target.error);
    };
}

(三)读取数据

1. 通过主键读取数据
javascript 复制代码
function getDataByKey(db, storeName, key) {
    return new Promise((resolve, reject) => {
        const transaction = db.transaction([storeName], "readonly");
        const objectStore = transaction.objectStore(storeName);
        const request = objectStore.get(key);

        request.onsuccess = function (event) {
            console.log("通过主键查询结果", event.target.result);
            resolve(event.target.result);
        };
        request.onerror = function (event) {
            console.error("查询失败", event.target.error);
            reject(event.target.error);
        };
    });
}
2. 通过索引读取数据
javascript 复制代码
function getDataByIndex(db, storeName, indexName, indexValue) {
    return new Promise((resolve, reject) => {
        const transaction = db.transaction([storeName], "readonly");
        const objectStore = transaction.objectStore(storeName);
        const index = objectStore.index(indexName);
        const request = index.get(indexValue);

        request.onsuccess = function (event) {
            console.log("通过索引查询结果", event.target.result);
            resolve(event.target.result);
        };
        request.onerror = function (event) {
            console.error("查询失败", event.target.error);
            reject(event.target.error);
        };
    });
}
3. 使用游标遍历数据
javascript 复制代码
function cursorGetData(db, storeName) {
    return new Promise((resolve, reject) => {
        const list = [];
        const transaction = db.transaction([storeName], "readonly");
        const objectStore = transaction.objectStore(storeName);
        const request = objectStore.openCursor();

        request.onsuccess = function (event) {
            const cursor = event.target.result;
            if (cursor) {
                list.push(cursor.value);
                cursor.continue();
            } else {
                resolve(list);
            }
        };
        request.onerror = function (event) {
            console.error("遍历失败", event.target.error);
            reject(event.target.error);
        };
    });
}

(四)更新数据

javascript 复制代码
function updateData(db, storeName, data) {
    const transaction = db.transaction([storeName], "readwrite");
    const objectStore = transaction.objectStore(storeName);
    const request = objectStore.put(data);

    request.onsuccess = function () {
        console.log("数据更新成功");
    };
    request.onerror = function (event) {
        console.error("数据更新失败", event.target.error);
    };
}

(五)删除数据

1. 通过主键删除数据
javascript 复制代码
function deleteDataByKey(db, storeName, key) {
    const transaction = db.transaction([storeName], "readwrite");
    const objectStore = transaction.objectStore(storeName);
    const request = objectStore.delete(key);

    request.onsuccess = function () {
        console.log("数据删除成功");
    };
    request.onerror = function (event) {
        console.error("数据删除失败", event.target.error);
    };
}
2. 通过索引删除数据
javascript 复制代码
function deleteDataByIndex(db, storeName, indexName, indexValue) {
    const transaction = db.transaction([storeName], "readwrite");
    const objectStore = transaction.objectStore(storeName);
    const index = objectStore.index(indexName);
    const request = index.openCursor(IDBKeyRange.only(indexValue));

    request.onsuccess = function (event) {
        const cursor = event.target.result;
        if (cursor) {
            cursor.delete();
            cursor.continue();
        }
    };
    request.onerror = function (event) {
        console.error("删除失败", event.target.error);
    };
}

四、实际应用场景

(一)数据可视化

在数据可视化应用中,需要存储大量的数据,每次请求服务器会消耗大量性能。使用 IndexedDB 可以将数据存储在客户端,提高性能。

(二)即时聊天工具

即时聊天工具需要存储大量的消息,使用 IndexedDB 可以将消息存储在本地,方便用户随时查看历史消息。

(三)存储空间不足时

当 LocalStorage 的存储空间不足时,可以使用 IndexedDB 提供更大的存储空间。

相关推荐
白兰地空瓶1 小时前
🚀你以为你在写 React?其实你在“搭一套前端操作系统”
前端·react.js
爱上妖精的尾巴1 小时前
6-4 WPS JS宏 不重复随机取值应用
开发语言·前端·javascript
似水流年QC2 小时前
深入探索 WebHID:Web 标准下的硬件交互实现
前端·交互·webhid
陪我去看海2 小时前
测试 mcp
前端
speedoooo3 小时前
在现有App里嵌入一个AI协作者
前端·ui·小程序·前端框架·web app
全栈胖叔叔-瓜州3 小时前
关于llamasharp 大模型多轮对话,模型对话无法终止,或者输出角色标识User:,或者System等角色标识问题。
前端·人工智能
三七吃山漆3 小时前
攻防世界——wife_wife
前端·javascript·web安全·网络安全·ctf
用户47949283569153 小时前
面试官问"try-catch影响性能吗",我用数据打脸
前端·javascript·面试
GISer_Jing3 小时前
前端营销技术实战:数据+AI实战指南
前端·javascript·人工智能
沐雪架构师4 小时前
大模型Agent面试精选15题(第四辑)-Agent与RAG(检索增强生成)结合的高频面试题
面试·职场和发展