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 提供更大的存储空间。

相关推荐
-今昭-12 分钟前
Logstash 管理
java·服务器·前端
名字还没想好☜24 分钟前
React 用自定义 useDebounce Hook 治好搜索框频繁请求:防抖、竞态取消与卸载清理
前端·javascript·react.js·react·hooks
浅念-28 分钟前
MySQL 索引底层完整详解|磁盘Page|B+树推导|聚簇非聚簇索引|索引SQL操作
大数据·数据库·b树·sql·mysql·面试·职场和发展
杉氧40 分钟前
Flutter 跨平台多端适配与 Android/iOS 一键自动化打包发布
android·前端·flutter
障碍的枫子40 分钟前
xss和CSRF的攻击和防御
前端·xss·csrf
用户921080262861 小时前
3. 给 Bubble 新增一个 Agent Variant
前端
抓不住时间的沙1 小时前
butterfly主题美化,打造属于自己的个性博客
java·开发语言·前端·javascript·node.js·github
众人皆醒我独醉1 小时前
GPU 集群 IaC:Terraform + Ansible 部署自动化
面试·ansible·gpu
kyriewen1 小时前
前端切图仔被 AI 新闻淹死的第 N 天,我用 TRAE Work 定时任务救了自己
前端·人工智能·trae
京东云开发者1 小时前
【全栈实践】第一个 AI Agent 项目:从零搭建 AI 音频创作助手(高级篇)
前端·agent·音视频开发