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

相关推荐
一 乐9 分钟前
民宿|基于java的民宿推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·源码
sunny-ll15 分钟前
【C++】详解vector二维数组的全部操作(超细图例解析!!!)
c语言·开发语言·c++·算法·面试
testleaf38 分钟前
前端面经整理【1】
前端·面试
好了来看下一题40 分钟前
使用 React+Vite+Electron 搭建桌面应用
前端·react.js·electron
啃火龙果的兔子40 分钟前
前端八股文-react篇
前端·react.js·前端框架
小前端大牛马1 小时前
react中hook和高阶组件的选型
前端·javascript·vue.js
刺客-Andy1 小时前
React第六十二节 Router中 createStaticRouter 的使用详解
前端·javascript·react.js
秋田君2 小时前
深入理解JavaScript设计模式之策略模式
javascript·设计模式·策略模式
潘小磊3 小时前
高频面试之11Flink
面试·flink
萌萌哒草头将军3 小时前
🚀🚀🚀VSCode 发布 1.101 版本,Copilot 更全能!
前端·vue.js·react.js