IndexedDB简介与使用教程

2019年11月18日 0 条评论 277 次阅读 0 人点赞

IndexDB简介


IndexedDB是一个事务型数据库系统,类似于基于SQL的RDBMS。 然而,不像RDBMS使用固定列表,IndexedDB是一个基于JavaScript的面向对象的数据库。 IndexedDB允许您存储和检索用索引的对象;可以存储结构化克隆算法支持的任何对象。 您只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务

注意: 正如大多数的web储存解决方案一样,IndexedDB也遵守同源策略。 因此当你在某个域名下操作储存数据的时候,你不能操作其他域名下的数据。

储存限制和回收标准

有许多Web技术在客户端(即本地磁盘)存储各种数据。IndexedDB是最常见的一个。浏览器计算分配给Web数据存储的空间以及达到该限制时要删除的内容的过程并不简单,并且在浏览器之间有所不同。浏览器存储限制和回收标准尝试解释这是如何工作的,至少在火狐的情况下是如此。 使用IndexedDB,你可以使用一个key作为索引进行存储或者获取数据。 你可以在事务(transaction)中完成对数据的修改。

indexedDB不使用结构化查询语言(SQL)。它通过索引(index)所产生的指针(cursor)来完成查询操作,从而使你可以迭代遍历到结果集合。如果你不熟悉NoSQL系统,可以参考维基百科相关文章

名词解释


数据库(database)

一个信息库,通常包含一个或多个 object stores. 每个数据库必须包含以下内容:
名字(Name):它标识了一个特定源中的数据库,并且在数据库的整个生命周期内保持不变。  此名字可以为任意字符串值(包括空字符串)。
当前版本(version):当一个数据库首次创建时,它的 version 为1,除非另外指定. 每个数据库在任意时刻只能有一个 version。

对象仓库(object store)

数据在数据库中存储的方式, 数据以键值对形式被对象仓库永久持有。对象仓库中的的数据以 keys 升序排列。

每一个对象仓库在同一个数据库中必须有唯一的名字。对象存储可以有一个 key generator 和一个 key path如果对象仓库有 key path,则使用 in-line keys; 否则使用 out-of-line keys

关于对象仓库的详细文档,请参考 IDBObjectStore 或者 IDBObjectStoreSync

数据库连接(database connection)

通过打开数据库创建的操作。一个给定的数据库可以同时拥有多个连接。

事务(transaction)

在一个特定的数据库上,一组具备原子性和持久性的数据访问和数据修改的操作。它是你与数据库交互的方式。并且,任何对于数据库中的数据读和修改的操作只能在事务中进行。

一个数据库连接可以拥有多个与之关联的事务,只要进行写操作事务的作用域不相互重合。事务的作用域在事务被创建时就被确定,指定事务能够进行交互的对象仓库(object store),作用域一旦被确定就会在整个生命周期中保持不变。举个例子,如果一个数据库连接已经有了一个进行写操作的事务,其作用域覆盖 flyingMonkey 对象仓库,你可以开启新的事务其作用于 unicornCentaur 和 unicornPegasus 对象仓库。对于读操作的事务,你可以同时拥有多个,即使他们有重叠的作用域。

事务被期望拥有较短的生命周期,所以浏览器会终止一个消耗时间过长的事务,为了释放存储资源,运行过久的事务会被锁定。你可以中断一个事务,来回滚事务中对数据库进行的操作。并且你甚至不需要等待事务开始或激活就可以中断它。

事务有三种模式:读写、只读和版本变更。创建和删除对象仓库(object store)的唯一方法就是通过调用版本变更事务。了解更多关于事务类型的内容,请参考 IndexedDB

因为所有的事情都在事务中发生,所以它是 IndexedDB 中非常重要的一个概念。了解更多关于事务,尤其是关于它和版本控制的关联,查看 IDBTransaction 中的参考文档。关于同步接口的文档,查看 IDBTransactionSync

使用教程


打开数据库

let db
const DBOpenRequest = window.indexedDB.open(dbName, version)
// 如果数据库打开失败
  DBOpenRequest.onerror = () => {
    console.log('数据库打开异常')
  }
  
  DBOpenRequest.onsuccess = () => {        
    // 存储数据结果
    db = DBOpenRequest.result;
  }

创建object store(数据表)信息

DBOpenRequest.onupgradeneeded = (event) => {
    const db = event.target.result;
    
    db.onerror = function() {
      console.log('数据库打开失败');
    };
    
    // 创建一个数据库存储对象
    const objectStore = db.createObjectStore(dbName, { 
      keyPath: 'id'
    });
    
    objectStore.createIndex('id', 'id', {
      unique: true    
    })
};

这个示例中创建了in-line keysobject store,要求所有存储的数据中都要含有id字段,并且以此创建索引,方便后续针对此字段的查找。

createObjectStore的第二个参数即可指定in-line keys中的keyPath

objectStore.createIndex的第一个参数是存储结构object store的key值,第二个字段是存储结构中的key字段对应的要存储的数据对象中的属性值

也可以创建out-of-line keysobject store

// 使用自动生成的递增数字作为键值
const objectStore = db.createObjectStore(dbName, { autoIncrement: true });

objectStore.createIndex('id', 'id', {
  unique: true    
})

增加/更新记录

add接口,在明确能区分是增加还是更新操作时,建议增加用add接口与,更新用put接口,以提高性能。

但是有些场景是无法区分是增加或者是更新操作的,譬如某个操作后需要更新数据,但是并不知道这条数据之前是否已经存在,那么都使用put接口即可,put接口在没有记录是会增加,存在记录时则更新

const transaction = this.db.transaction([dbName], "readwrite")
// 打开已经存储的数据对象
const objectStore = transaction.objectStore(dbName)
// 添加到数据对象中
const objectStoreRequest = objectStore.put(value)  // 或者使用objectStore.add(value)   
objectStoreRequest.onsuccess = () => {
  resolve()
}
objectStoreRequest.onerror = (err) => {
  console.error(`从数据库读取${key}异常`,err)
  reject()
}

注意:如果创建的表为out-of-line keys类型的object store,那么put()方法中的value不为单参数的“{}”对象形式,而是put(值,键)的形式。

查询记录

查询记录需要使用cursorcursor类似一个指针,在数据记录中一条条移动遍历出每条记录

let recordList = []
const objectStore = db.transaction(dbName).objectStore(dbName);
objectStore.openCursor().onsuccess = function(event) {
      var cursor = event.target.result;
      // 如果没有遍历完,继续下面的逻辑
      if (cursor) {
          recordList.push(cursor.value);            
          // 继续下一个游标项
          cursor.continue();
      // 如果全部遍历完毕
      } else {
          console.log('存储的数据为',JSON.stringify(recordList))
      }
  }

删除记录

const transaction = db.transaction([dbName], "readwrite")
// 打开已经存储的数据对象
const objectStore = transaction.objectStore(dbName)
// 添加到数据对象中
const objectStoreRequest = objectStore.delete(id)  
objectStoreRequest.onsuccess = () => {
    console.log(`删除${id}成功`)
}
objectStoreRequest.onerror = (err) => {
  console.error(`从数据库删除${id}异常`, err)
}

参考资料


http://echizen.github.io/tech/2018/06-23-indexdb

教程及介绍

http://www.softwhy.com/article-10254-1.html

in-line key与out-in-line key实例

chao

chao

这个人太懒什么东西都没留下

文章评论(0)

你必须 登录 才能发表评论