IndexedDB初体验

154 阅读4分钟

什么是IndexedDB

IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))。 该API使用索引实现对数据的高性能搜索

封装IndexedDB

通过类来封装可以提高可读性、 可拓展性、可维护性强

class useIndexedDB{ constructor(){ } }
  • 检查浏览器是否兼容
window.myIndexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
this.isIndexedDB = Boolean(window.myIndexedDB);
if(this.isIndexedDB){
    console.log('当前浏览器支持 IndexedDB');
}else{
    console.log('您的浏览器不支持 IndexedDB')
}
  • 连接数据库
//databaseName 数据库名 version 数据库版本
this.dbRequest = window.myIndexedDB.open(databaseName,version)
// 数据库打开失败
this.dbRequest.onerror = (event) => {};
// 数据库首次创建自动触发
this.dbRequest.onupgradeneeded = (event) => {};
  • 创建数据库字段
this.dbRequest.onupgradeneeded = (event) => {
    this.db = event.target.result;
    //创建数据库并指定id为主键,自动递增
	this.objectStore = db.createObjectStore(this.databaseTableName, { keyPath: "id", autoIncrement: true });
    // 定义表中将包含哪些数据项
    /*
     indexName:要创建的索引的名称,必须是一个字符串。该名称必须在对象存储空间中是唯一的,否则会引发异常。
     keyPath:指定要从存储在对象存储空间中的对象中提取的属性的名称或属性路径,用于创建索引。可以是一个字符串或字符串数组。
     options:一个可选的配置对象,用于指定索引的各种选项,包括:
		unique:一个布尔值,表示索引是否应该是唯一的。默认值为 false。
		multiEntry:一个布尔值,表示索引是否应该支持多个条目具有相同的键。默认值为 false。
		locale:一个字符串,表示用于排序的语言环境。默认值为 undefined,表示使用当前的环境。
		caseFirst:一个字符串,表示在排序时应该如何处理字母的大小写。可选值为 "upper"、"lower" 或 					"false"。默认值为 undefined,表示使用当前的环境。
     */
	this.objectStore.createIndex(indexName, keyPath, options);
};
  • 启动新事务
this.dbRequest.onsuccess = (event) => {
	const db = event.target.result;
    // 判断当前数据库中是否有当前表
	if (db.objectStoreNames.contains(this.databaseTableName)) {
        // transaction启动一个新的事务
        /*
          [databaseTableName] 一个字符串或字符串数组,标识需要开启的一张或多个表
          mode 一个字符串,表示需要在该事务中进行的操作类型。可选值包括 "readonly"(只读模式)和 				"readwrite"(读写模式)。如果未指定该参数,则默认为只读模式。
          options 一个可选的配置对象,用于指定事务的各种选项
          	durability:表示事务的持久性。可选值包括 "default"、"strict" 和 "relaxed"
          	timeout:表示事务的超时时间(毫秒单位)如果在超时时间内未能完成事务,则事务将被回滚
          	signal:一个 AbortSignal 对象,表示用于终止事务的信号。如果该信号被触发,则事务将被回滚。
         */
		const transaction = db.transaction(databaseTableName, mode, options);
        // 获取当前事务中指定的存储空间
		const objectStore = transaction.objectStore(this.databaseTableName);
	} else {
        // 没有就新建表
		this.db.createObjectStore(this.databaseTableName, { keyPath: "id" });
	}
};

init

抽取一个公共方法,直接获取事务中的表

init() {
    return new Promise((resolve, reject) => {
        this.dbRequest = window.myIndexedDB.open(this.databaseName, this.version);
        this.dbRequest.onsuccess = (event) => {
            const db = event.target.result;
            if (db.objectStoreNames.contains(this.databaseTableName)) {
                const transaction = db.transaction([this.databaseTableName], "readwrite");
                const objectStore = transaction.objectStore(this.databaseTableName);
                resolve(objectStore);
            } else {
                this.db.createObjectStore(this.databaseTableName, { keyPath: "id" });
            }
        };
        this.dbRequest.onerror = (event) => {
            reject(event);
        };
    });
}

select

select(key) {
    return new Promise((resolve, reject) => {
        this.init().then((objectStore) => {
            // 通过传入的索引获取指定数据
            const selectObjectStore = objectStore.get(key);
            selectObjectStore.onsuccess = function () {
                console.log("查询数据成功");
                resolve(selectObjectStore.result);
            };
            selectObjectStore.onerror = function () {
                console.log("查询数据失败");
                reject(selectObjectStore.result);
            };
        });
    });
}

selectAll

selectAll() {
    return new Promise((resolve, reject) => {
        this.init().then((objectStore) => {
            const results = [];
            // 通过游标循环出所有数据
            const cursorObjectStore = objectStore.openCursor();
            cursorObjectStore.onsuccess = function (event) {
                const cursor = event.target.result;
                if (cursor) {
                    results.push(cursor.value);
                    cursor.continue();
                } else {
                    console.log("查询游标成功");
                    resolve(results);
                }
            };
            cursorObjectStore.onerror = function () {
                console.log("查询游标失败");
                reject(cursorObjectStore.result);
            };
        });
    });
}

insert

insert(options) {
    return new Promise((resolve, reject) => {
        this.init().then((objectStore) => {
            // 插入一条数据 (要包含id值)
            const insertObjectStore = objectStore.add(options);
            insertObjectStore.onsuccess = function (event) {
                console.log("插入数据成功");
                resolve(insertObjectStore.result);
            };
            insertObjectStore.onerror = function () {
                console.log("插入数据失败");
                reject(insertObjectStore.result);
            };
        });
    });
}

delete

delete(key){
    return new Promise((resolve, reject) => {
        this.init().then((objectStore) => {
            // 删除指定数据
            const clearRequest = objectStore.delete(key);
            clearRequest.onsuccess = function () {
                console.log("删除数据成功");
                resolve("删除数据成功");
            };
            clearRequest.onerror = function () {
                console.log("删除数据失败");
                reject(clearRequest.result);
            };
        });
    });
}

deleteAll

deleteAll() {
    return new Promise((resolve, reject) => {
        this.init().then((objectStore) => {
            // 清楚表中所有数据
            const clearRequest = objectStore.clear();
            clearRequest.onsuccess = function (event) {
                console.log("删除数据成功");
                resolve("删除数据成功");
            };
            clearRequest.onerror = function () {
                console.log("删除数据失败");
                reject(clearRequest.result);
            };
        });
    });
}

完整代码

class useIndexedDB {
    /**
   * @param databaseName
   * @param databaseTableName
   */
    constructor(databaseName, databaseTableName) {
        this.isIndexedDB = true;
        window.myIndexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
        this.isIndexedDB = Boolean(window.myIndexedDB);
        if (this.isIndexedDB){
            this.db = null;
            this.version = 1;
            this.databaseName = databaseName;
            this.databaseTableName = databaseTableName;
            this.dbRequest = window.myIndexedDB.open(this.databaseName, 1);

            this.dbRequest.onerror = (event) => {
                console.log("error", event);
            };
            this.dbRequest.onupgradeneeded = (event) => {
                this.db = event.target.result;
                this.store = this.db.createObjectStore(this.databaseTableName, { keyPath: "id" });
            };
        }
    }

    init() {
        return new Promise((resolve, reject) => {
            this.dbRequest = window.myIndexedDB.open(this.databaseName, this.version);
            this.dbRequest.onsuccess = (event) => {
                const db = event.target.result;
                if (db.objectStoreNames.contains(this.databaseTableName)) {
                    const transaction = db.transaction([this.databaseTableName], "readwrite");
                    const objectStore = transaction.objectStore(this.databaseTableName);
                    resolve(objectStore);
                } else {
                    this.db.createObjectStore(this.databaseTableName, { keyPath: "id" });
                }
            };
            this.dbRequest.onerror = (event) => {
                reject(event);
            };
        });
    }

    select(key) {
        return new Promise((resolve, reject) => {
            this.init().then((objectStore) => {
                const selectObjectStore = objectStore.get(key);
                selectObjectStore.onsuccess = function () {
                    console.log("查询数据成功");
                    resolve(selectObjectStore.result);
                };
                selectObjectStore.onerror = function () {
                    console.log("查询数据失败");
                    reject(selectObjectStore.result);
                };
            });
        });
    }

    selectAll() {
        return new Promise((resolve, reject) => {
            this.init().then((objectStore) => {
                const results = [];
                const cursorObjectStore = objectStore.openCursor();
                cursorObjectStore.onsuccess = function (event) {
                    const cursor = event.target.result;
                    if (cursor) {
                        results.push(cursor.value);
                        cursor.continue();
                    } else {
                        console.log("查询游标成功");
                        resolve(results);
                    }
                };
                cursorObjectStore.onerror = function () {
                    console.log("查询游标失败");
                    reject(cursorObjectStore.result);
                };
            });
        });
    }

    insert(options) {
        return new Promise((resolve, reject) => {
            this.init().then((objectStore) => {
                const insertObjectStore = objectStore.add(options);
                insertObjectStore.onsuccess = function (event) {
                    console.log("插入数据成功");
                    resolve(insertObjectStore.result);
                };
                insertObjectStore.onerror = function () {
                    console.log("插入数据失败");
                    reject(insertObjectStore.result);
                };
            });
        });
    }
    delete(key){
        return new Promise((resolve, reject) => {
            this.init().then((objectStore) => {
                const clearRequest = objectStore.delete(key);
                clearRequest.onsuccess = function () {
                    console.log("删除数据成功");
                    resolve("删除数据成功");
                };
                clearRequest.onerror = function () {
                    console.log("删除数据失败");
                    reject(clearRequest.result);
                };
            });
        });
    }
    deleteAll() {
        return new Promise((resolve, reject) => {
            this.init().then((objectStore) => {
                const clearRequest = objectStore.clear();
                clearRequest.onsuccess = function () {
                    console.log("删除数据成功");
                    resolve("删除数据成功");
                };
                clearRequest.onerror = function () {
                    console.log("删除数据失败");
                    reject(clearRequest.result);
                };
            });
        });
    }
}

其中update没有封装,可以通过以下两种方案修改

  1. 回调调用获取该条数据使用get方法,拿到数据修改调用put可以修改
  2. 可以通过游标openCursor,执行获取想要修改的那一条数据进行修改

第一次尝试使用IndexedDB,如有错误,多多指正相互学习.