IndexedDB简介与入门

  

背景

在本地离线存储的场景中,IndexedDB作为一个nosql的本地DB存储一直发挥着重要的作用。在需要存储大量数据时,IndexedDB能够有效地满足你的需求。下面,我将简单介绍下IndexedDB的简单使用方法和在我阅读W3C规范文档时看到的一些需要注意的细节。实例大部分参照MDN中的介绍实例,同时对整体逻辑和实例做了一些改动。

使用方法

打开数据库

我们使用window.indexedDB.open(DBName)来打开数据库。具体实例如下:


  1. const request = window.indexedDB.open(DBName); 
  2. request.onsuccess = function(event) { 
  3.     //request === event.target; 
  4. request.onerror = function(event) {}  

当数据库连接时,会返回一个IDBOpenDBRequest对象。在连接建立成功时,会触发onsuccess事件,其中函数参数event的target属性就是request对象。

创建和更新数据库版本号

window.indexedDB.open的第二个参数即为版本号。在不指定的情况下,默认版本号为1。具体实例如下:


  1. const request = window.indexedDB.open(DBName, 2); 

在需要更新数据库的schema(模式)时,需要更新版本号。此时我们指定一个高于之前版本的版本号,就会触发onupgradeneeded事件。类似的,在第一次创建时,也会触发此事件。

我们需要注意的是,版本号是一个unsigned long long数字,这意味着它可以是一个非常大的整数。但是,它不能是一个小数,否则它将会被转为最近的整数,同时有可能导致onUpgradeneeded事件不触发(bug)。

构建数据库

我们使用createObjectStore来创建一个存储空间。同时,使用createIndex来创建索引。具体实例如下:


  1. const objectStore = db.createObjectStore('customers'); 
  2.  
  3. objectStore.createIndex('name', 'name', {unique:false});  

我们从第一个函数createObjectStore开始说起。该函数接受两个参数,第一个参数为存储空间的名称,即我们上面的customers。同时,它还有第二个可选参数,keyPath指定存储的key值为存储对象的某个属性,autoIncrement指定了key值是否自增(当key值为默认的从1开始到2^53的整数时)。具体实例如下:


  1. const objectStore = db.createObjectStore('customers',{keyPath:'id', autoIncrement:true}); 

第二个函数为createIndex,它的第一个参数为索引的名称,第二个参数是指定根据存储数据的哪一个属性来构建索引,第三个属性unique为是否允许指定的索引值是否可以相等。具体示例如下:


  1. objectStore.createIndex('by_name', 'name', {unique:false}); 
  2.  
  3. objectStore.createIndex('by_email', 'email', {unique:true});  

当存储空间初始化完成后,我们需要把数据放入存储空间中,我们可以直接调用add方法将数据放入存储空间内,具体实例如下:


  1. //方法1,规范文档推荐使用, key值如果指定自增,可以不填 
  2. objectStore.put(data, key); 
  3. //方法2,key值同上 
  4. objectStore.add(data, key);  

事务

在IndexedDB中,我们也能够使用事务来进行数据库的操作。事务有三个模式:

  • readOnly,只读
  • readwrite,读写
  • versionchange,数据库版本变化

我们创建一个事务时,需要从上面选择一种模式,如果不指定的话,则默认为只读模式。具体实例如下:


  1. const transition = db.transition(['customers'], 'readwrite'); 

事务函数transition的第一个参数为需要关联的存储空间,第二个可选参数为事务模式。与上面类似,事务成功时也会触发onsuccess函数,失败时触发onerror函数。

事务的操作都是原子性的。

删除

使用delete函数即可删除数据。具体使用方法如下:


  1. const request = db.transaction(['customers'], 'readwrite').objectStore('customers').delete(author); 

获取数据

get方法

最简单的方法就是使用自带的get函数来获取存储空间的值,具体实例如下:


  1. db.transition(['customer']).objectStore('customer').get(keyName).onuccess = function(){}; 

游标方法

我们使用openCursor来创建游标。


  1. const objectStore = db.transaction('customers').objectStore('customers'); 
  2.  
  3. objectStore.openCursor().onsuccess = function(event) { 
  4.   const cursor = event.target.result; 
  5.   if (cursor) { 
  6.     alert(cursor.value.name); 
  7.     cursor.continue(); 
  8.   } 
  9.   else { 
  10.     alert('No more entries!'); 
  11.   } 
  12. }; 

使用游标时有一个需要注意的地方,当游标便利整个存储空间但是并未找到给定条件的值时,仍然会触发onsuccess函数。

同时,如果你想要限定你在游标中看到的值的范围,你可以使用一个key range对象然后把它作为第一个参数传给openCursor或是openKeyCursor方法。你可以构造一个只允许一个单一key的 key range,或者一个具有下限或上限,或者一个既有上限也有下限。边界可以是闭合的(也就是说key range包含给定的值)或者是“开放的”(也就是说key range不包括给定的值)。具体实例如下:


  1. // 只匹配 'Donna' 
  2. const singleKeyRange = IDBKeyRange.only('Donna'); 
  3.  
  4. // 匹配所有在 'Bill' 前面的, 包括 'Bill' 
  5. const lowerBoundKeyRange = IDBKeyRange.lowerBound('Bill'); 
  6.  
  7. // 匹配所有在 “Bill” 前面的, 但是不需要包括 'Bill' 
  8. const lowerBoundOpenKeyRange = IDBKeyRange.lowerBound('Bill', true); 
  9.  
  10. // Match anything up to, but not including, 'Donna' 
  11. const upperBoundOpenKeyRange = IDBKeyRange.upperBound('Donna', true); 
  12.  
  13. //Match anything between 'Bill' and 'Donna', but not including 'Donna' 
  14. const boundKeyRange = IDBKeyRange.bound('Bill', 'Donna', false, true); 
  15.  
  16. index.openCursor(boundKeyRange).onsuccess = function(event) { 
  17.   const cursor = event.target.result; 
  18.   if (cursor) { 
  19.     // Do something with the matches. 
  20.     cursor.continue(); 
  21.   } 
  22. };  

IDBKeyRange对象的lowerBound和upperBound方法分别表示检索指定key值前或者后的范围(第二个参数指定边界是否闭合,如果为true则不闭合)。

有时候你可能想要以倒序而不是正序(所有游标的默认顺序)来遍历。切换方向是通过传递prev到 openCursor方法来实现的。


  1. objectStore.openCursor(null, IDBCursor.prev).onsuccess = function(event) { 
  2.   const cursor = event.target.result; 
  3.   if (cursor) { 
  4.     // Do something with the entries. 
  5.     cursor.continue(); 
  6.   } 
  7. };  

因为 “name” 索引不是唯一的,那就有可能存在具有相同 name 的多条记录。要注意的是这种情况不可能发生在对象存储空间上,因为键必须永远是唯一的。如果你想要在游标在索引迭代过程中过滤出重复的,你可以传递 nextunique (或 prevunique 如果你正在向后寻找)作为方向参数。 当 nextunique 或是 prevunique 被使用时,被返回的那个总是键最小的记录。

索引方法

在前面构建数据库时,我们创建了两个索引。现在,我们就通过这两个索引来演示如何通过索引进行搜索。具体实例如下:


  1. const index = objectStore.index('by_name'); 
  2. //第一种,使用get方法 
  3. index.get(name).onsuccess = function(){ 
  4.     alert(event.target.result.name); 
  5. //第二种,使用游标 
  6. //普通游标 
  7. index.openCursor().onsuccess = function(event) { 
  8.   const cursor = event.target.result; 
  9.   if (cursor) { 
  10.     // cursor.key 是一个 name, 就像 'Bill', 然后 cursor.value 是整个对象。 
  11.     alert('Name: ' + cursor.key + ', id' + cursor.value.id + ', email: ' + cursor.value.email); 
  12.     cursor.continue(); 
  13.   } 
  14. }; 
  15.  
  16. //键游标 
  17. index.openKeyCursor().onsuccess = function(event) { 
  18.   const cursor = event.target.result; 
  19.   if (cursor) { 
  20.     // cursor.key is 一个 name, 就像 'Bill', 然后 cursor.value 是那个id,即存储对象的key值。 
  21.     alert('Name: ' + cursor.key + ', 'id: ' + cursor.value); 
  22.     cursor.continue(); 
  23.   } 
  24. };  

异常处理

在浏览器有如下操作的情况下,indexedDB可能会出现异常:

  • 用户清除浏览器缓存
  • 存储空间超过大小限制

W3C规范文档需要注意的应用点

key值能够接受的数据类型

在IndexedDB中,key值可以接受一下几种类型的值:

  • Number
  • Date
  • String
  • ArrayBuffer
  • Array

具体说明可以参考此处。

key path能够接受的数据类型

在IndexedDB中,key path(主键)能够接接受如下数据类型:

  • Blob
  • File
  • Array
  • StringI

注:空格不能出现在key path中。

value能够接受的数据类型

在IndexedDB中,value能够接受ECMA-262中所有的值,例如String,Date,ImageDate等。

事务中断后,会不会影响key值的自增

IndexedDB在没有指定key值的时候就会采用自增的key值,不受其他任何影响。如果一个事务在中途中断,那么key值的自增将会从事务开始前的key开始。

IndexedDB的安全相关问题

IndexedDB也受到浏览器同源策略的限制。

总结

IndexedDB在本地存储中有着无可替代的作用,是替代关系型数据库websql的产品。在许多需要运用离线存储的场景下,IndexedDB能够给我们提供有效的支撑。但是,IndexedDB毕竟存在于客户端,会出现诸如用户清理缓存(Windows下更为常见)等破坏数据的情况,因此建议作为一个优化用户体验的方案,不能过多依赖。

作者:hjava

来源:51CTO

时间: 2025-01-21 12:17:37

IndexedDB简介与入门的相关文章

Python之路【1】:Python简介和入门

Python之路[第一篇]:Python简介和入门 python简介: 一.什么是python Python(英国发音:/ pa θ n/ 美国发音:/ pa θɑ n/),是一种面向对象.直译式的计算机程序语言. 每一门语言都有自己的哲学: pythonde 设计哲学是:"优雅"."明确"."简单" 二.python由来  1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.之

React Native 简介与入门

一.简介 ReactNative.png React Native 是Facebook发布的,可以让我们广大开发者使用JavaScript和React开发我们的应用,该提倡组件化开发,也就是说React Native给我们提供一个个封装好的组件让开发者来进行使用,甚至我们可以相关嵌套形成新的组件. 使用React Native我们可以维护多种平台(Web,Android和IOS)的同一份业务逻辑核心代码来创建原生应用. 现阶段Web APP的的体验还是无法达到Native APP的体验,所以这边

RDLC系列之一 简介和入门

一.简介 RDLC报表,通过Report Viewer Control来实现,制作微软RDLC报表由以下三部分构成:1.制作自己的DateSet集合(就是报表的数据集):2.制作自己的报表文件.rdlc文件,用于画做报表样式,里面有微软自带的导出和打印功能.制作显示报表的前台页面aspx文件,基本上就是插入一个ReportViewer然后关联上面的.rdlc文件,注意别忘了更新数据源和插入ScriptManager. 这种报表的易用性和可定制性,主要功能:       1.简单易用的控件,特别是

JavaWeb学习----JSP简介及入门(含Eclipse for Java EE及Tomcat的配置)

[前言] JSP本身是JavaWeb中的知识,但是在学习Android网络时,必然要涉及到与服务器之间的交互,所以学一下JSP以及其他JavaWeb的内容还是很有必要的,至少能明白程序在访问服务器时,整个过程的原理. 其实,在学习Android之前,Java和JavaWeb的知识都是要先学习的.本人是在2014年7月正式开始Android方向的研究学习,在这之前没有接触任何和计算机软件相关的知识(唯一相关的是,本科学过一门C语言课程,不过现在已经忘光了). 我们来看下面的这张图就知道了: 两张图

MongoDB中javascript脚本编程简介和入门实例_MongoDB

注:作者使用的mongodb版本为2.4.7. 入门例子 复制代码 代码如下: conn = new Mongo();db = conn.getDB("db-name");  //选择数据库db.auth("user-name","password");  //用户验证 var map = function() {    split_result = this.sentence.split(" ");    for (var

Spring BlazeDS Integration简介与入门

去年底Adobe与Spring共同宣布将联合开发一个新项目:Spring BlazeDS Integration.其目标是:开发者可以利用Spring开发模型通过Adobe Flex.BlazeDS.Spring以及Java技术创建RIA.这样我们就可以通过BlazeDS公开Spring管理的服务而无需额外的配置文件.其优势在于将Spring的易用性与Flex.BlazeDS以及Java整合起来以共同创建应用. 我将在本文中介绍Spring BlazeDS Integration项目对传统开发方

AJAX 简介及入门实例_AJAX相关

对于一个像我一样刚刚接触Web开发且无多少实际项目经验的新手而言,AJAX技术显得复杂而又深奥.经过两天的baidu.google,我对AJAX的基本原理有了一个大致的认识,在此总结一下. 1. 什么是AJAX? AJAX全称是异步的JavaScript和XML,是Asynchronous JavaScript and XML的缩写.AJAX技术用于创建交互式网页应用的网站开发,至于何为异步,后文会有解释. 1.1 桌面应用程序和Web应用程序 在详细讨论AJAX技术之前,需要先知道AJAX技术

苹果公司推出的新编程语言Swift简介和入门教程_IOS

一.Swift是什么? Swift是苹果于WWDC 2014发布的编程语言,这里引用The Swift Programming Language的原话: 复制代码 代码如下: Swift is a new programming language for iOS and OS X apps that builds on the best of C and Objective-C, without the constraints of C compatibility.Swift adopts sa

AJAX 简介及入门实例

对于一个像我一样刚刚接触Web开发且无多少实际项目经验的新手而言,AJAX技术显得复杂而又深奥.经过两天的baidu.google,我对AJAX的基本原理有了一个大致的认识,在此总结一下. 1. 什么是AJAX? AJAX全称是异步的JavaScript和XML,是Asynchronous JavaScript and XML的缩写.AJAX技术用于创建交互式网页应用的网站开发,至于何为异步,后文会有解释. 1.1 桌面应用程序和Web应用程序 在详细讨论AJAX技术之前,需要先知道AJAX技术