HTML5 IndexedDB

1,764 阅读6分钟
原文链接: blog.percymong.com

Indexed Database API,简称 IndexedDB,是在浏览器中保存结构化数据的一种数据库。

IndexedDB 的思想是创建一套 API,方便保存和读取 JavaScript 对象,同时还支持查询及搜索。(API 超级多~)

此外,IndexedDB 也遵循同源策略,并且大小也有限制。和 localStorage 相似,若非手动删除或调用 JavaScript 方法删除,IndexedDB 的数据会一直存在。

大小限制可以看这里:A research report on browser storage

IndexedDB API 汇总(只列出主要的)

  • window.indexedDB: 一个 IDBFactory 对象

IDBFactory 对象

  • IDBFactory.open(name[,version]): 发送一个连接指定数据库的请求
    • name: 数据库的名称
    • version: 可选值,数据库的版本,若未指定,默认为 1
    • 这个方法返回一个 IDBOpenDBRequest 对象
  • IDBFactory.deleteDatabase(name): 删除指定的数据库
    • 这个方法也返回一个 IDBOpenDBRequest 对象
  • IDBFactory.cmp(): 比较数据库。。没用过

IDBOpenDBRequest 对象

  • IDBOpenDBRequest.onsuccess: 请求成功时触发
    • event.target: 指向当前的 IDBOpenDBRequest 对象
    • event.target.result: 获取数据库对象(一个 IDBDatabase 对象
  • IDBOpenDBRequest.onerror: 请求发生错误时触发(比如请求比当前数据库版本低的数据库时会触发)
    • event.target: 指向当前的 IDBOpenDBRequest 对象
    • event.target.error: 获取发生错误的详细信息
  • IDBOpenDBRequest.onblocked: This event is triggered when the upgradeneeded should be triggered because of a version change but the database is still in use (that is, not closed) somewhere, even after the versionchange event was sent.
  • IDBOpenDBRequest.onupgradeneeded: 在请求的数据库版本不可用时触发(比如升级数据库,即请求的数据库版本比当前版本高时触发,或者说请求的数据库不存在时触发)
    • event.target: 指向当前的 IDBOpenDBRequest 对象
    • event.target.result: 获取数据库对象(一个 IDBDatabase 对象

IDBDatabase 对象

  • 属性

    • IDBDatabase.name: 返回当前数据库的名称
    • IDBDatabase.version: 返回当前数据库的版本
    • IDBDatabase.objectStoreNames: 返回一个类数组对象,存储着各个对象存储空间的名称
  • 事件

    • IDBDatabase.onabort: 获取数据库被拒绝时触发
    • IDBDatabase.onclose: 关闭数据库时触发
    • IDBDatabase.onerror: 获取数据库失败时触发
    • IDBDatabase.onversionchange: 数据库结构发生变化时触发【fired when a database structure change (IDBOpenDBRequest.onupgradeneeded event or IDBFactory.deleteDatabase) was requested elsewhere (most probably in another window/tab on the same computer)】
  • IDBDatabase.createObjectStore(name [,optionalObj]): 新建一个对象存储空间(类似数据库中的数据表)
    • name: 对象存储空间的名称
    • optionalObj: 一个对象,属性 keyPath 声明主关键字;属性 autoIncrement 默认为 false,设置为 true 时可以自动生成唯一的数字
    • 主关键字是唯一标识每条数据的信息
    • 该方法返回一个 IDBObjectStore 对象
  • IDBDatabase.deleteObjectStore(name): 删除指定名称的对象存储空间,什么也不返回
  • IDBDatabase.close(): 在所有的数据操作结束后,立即关闭与数据库的连接
    • The connection is not actually closed until all transactions created using this connection are complete
  • IDBDatabase.transaction(storeName[,mode]): 获取指定的对象存储空间
    • storeName: 需要获取的对象存储空间的名称,可以是一个字符串、一个数组(获取多个对象存储空间)
    • mode: 权限设置,一个字符串,readonly(只读)、readwrite(可以读写)、readwriteflush(最后这个是非标准,一般不使用)
    • 该方法返回一个 IDBTransaction 对象

createObjectStore 和 deleteObjectStore 方法只能在最开始连接数据库的 IDBOpenDBRequest.onupgradeneeded 中进行调用,不能在 IDBOpenDBRequest.onsuccess 中进行调用,否则报错。

You can only call createObjectStore or deleteObjectStore when you are in a versionchange transaction, which rougly corresponds to the upgradeneeded event handler.

IDBTransaction 对象

  • 数据操作 作为一个术语,用来描述对数据表数据的所有操作(读取、修改、插入或更新数据)
  • transaction,中文翻译过来是事务办理的意思。
  • 数据库事务就是一个抽象单元,它包含了一次或多次对数据库的数据操作。
  • 如果事务中的任何一部分数据操作失败了,则事务的所有操作都会撤销,数据库会恢复到事务之前的状态

数据所有操作(读取、修改、插入或删除)均在 transactions 中完成。

  • 属性

    • IDBTransaction.db: 返回当前对连接的数据库的引用(返回一个 IDBDatabase 对象
    • IDBTransaction.mode: 返回当前操作的权限
    • IDBTransaction.error: 在 transaction 不成功时返回的错误消息
  • 事件

    • IDBTransaction.oncomplete: 在 transaction 全部完成时触发
  • IDBTransaction.abort(): 放弃本次连接的 transaction 的所有操作

  • IDBTransaction.objectStore(name): 获取指定名称的对象存储空间
    • 该方法返回一个 IDBObjectStore 对象

IDBObjectStore 对象

由于这个对象的实例方法有点多,下面只列出部分,详细的请查阅 MDN

  • IDBObjectStore.add(value[,key]): 添加数据
    • value:存储的数据
    • key:用来识别数据的键
    • 该方法返回一个 IDBRequest 对象
    • 可以用 success 事件来监听是否添加数据成功
  • IDBObjectStore.clear(): 清除数据

麻蛋,太多了,不想继续写了,以后用到再来补充吧~

IDBRequest 对象

成功向 IndexedDB 添加数据的一个例子

这里只写了为数据库添加数据的代码,没有写查询数据、删除数据的操作。


    // 全局变量,用来引用数据库
let database;
// 向指定的数据库发出连接请求
let DBOpenRequest = window.indexedDB.open('firstDB', 4.0);
// 在请求的数据库版本不可用时触发,比如数据库不存在
DBOpenRequest.onupgradeneeded = function(event) {
    console.log('upgradeneeded happens~');
    // 得到对数据库的引用
    database = event.target.result;
    // 为数据库添加 2 个对象存储空间
    database.createObjectStore('person store', {
        keyPath: 'objKey'
    });
    database.createObjectStore('animal store', {
        keyPath: 'objKey'
    });
};
DBOpenRequest.onsuccess = function(event) {
    console.log('连接数据库成功~');
    // 得到对数据库的引用
    database = event.target.result;
    // 创建一个事务
    // 下面函数第一个参数是需要被引入这个事务的对象存储空间的名称
    let transaction = database.transaction(['person store', 'animal store'], 'readwrite');
    // 获取指定的对象存储空间的引用
    let personStore = transaction.objectStore('person store');
    // 新建3个测试对象
    let user1 = {
        objKey: 11111,
        name: 'percy',
        age: 22,
        skills: ['html', 'css', 'js']
    };
    let user2 = {
        objKey: 22222,
        name: 'jake',
        age: 30,
        skills: {
            python: 'master',
            javascript: 'master',
            java: 'know a little'
        }
    };
    let user3 = {
        objKey: 33333,
        name: 'alice',
        age: 18,
        skills: 'I have beautiful face. Lol...'
    };
    // 为指定的对象存储空间添加数据
    // 这里使用 put 方法添加数据,注意 add 和 put 方法的不同
    // 可以使用互换下面语句试试看
    // let DBRequest = personStore.add(data);
    let DBRequest = personStore.put(user1);
    // 为了节省代码,就不为下面的两个对象添加检错机制了
    personStore.put(user2);
    personStore.put(user3);
    // 监听写入数据时是否出错
    DBRequest.onerror = function(event) {
        console.log('为 person store 写入数据出错~' + event.target.error);
    };
    // 监听数据是否写入成功
    DBRequest.onsuccess = function() {
        console.log('为 person store 添加数据成功~');
    };
};
DBOpenRequest.onblocked = function(event) {
    console.log('blocked happens~');
};
DBOpenRequest.onerror = function(event) {
    console.log('获取数据库时发生错误:' + event.target.error);
};

实际应用

  • 创建自给自足的离线应用
  • 优化性能,将部分频繁使用的服务器数据保存到本地的 IndexedDB 数据库中(超级定制缓存)
  • 改进本地存储(localStorage、sessionStorage),用 IndexedDB 来存储比较大的数据

本文对你有帮助?欢迎扫码加入前端学习小组微信群: