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 分钟前
Vue3 学习教程,从入门到精通,使用 VSCode 开发 Vue3 的详细指南(3)
前端·javascript·vue.js·学习·前端框架·vue·vue3
姑苏洛言27 分钟前
搭建一款结合传统黄历功能的日历小程序
前端·javascript·后端
hackchen1 小时前
Go与JS无缝协作:Goja引擎实战之错误处理最佳实践
开发语言·javascript·golang
你的人类朋友2 小时前
🤔什么时候用BFF架构?
前端·javascript·后端
知识分享小能手2 小时前
Bootstrap 5学习教程,从入门到精通,Bootstrap 5 表单验证语法知识点及案例代码(34)
前端·javascript·学习·typescript·bootstrap·html·css3
一只小灿灿2 小时前
前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
前端·opencv·计算机视觉
前端小趴菜052 小时前
react状态管理库 - zustand
前端·react.js·前端框架
zhuiQiuMX3 小时前
字节面试手撕中等题但还没做出来
面试
Jerry Lau3 小时前
go go go 出发咯 - go web开发入门系列(二) Gin 框架实战指南
前端·golang·gin