About IndexDB(转)

IndexedDB是用于客户端的大量的结构化数据存储和使用索引高效率搜索数据的API,它是基于W3C拟定的草案索引数据库的API。相对DOM存储的小存储数据量,IndexedDB具有大容量的数据存储功能,它分别为同步数据和异步数据提供的API,但目前只有异步数据的API在Gecko2.0 上实现。

 

一、 概述

1. IndexedDB存储为键值对:它可以存储一些复杂的对象,而键可以存储这些对像的属性值,并且可以使用索引对对象的属性的快速检索。

2. IndexedDB建立在交互数据库模型的基础上:任何对IndexedDB的操作都发生一个交互操作(transaction),如它提供的索引、表、游标等均与一个transaction关联,它定义了交互的生存时间与结束时抛出的事件,这样能很好的处理web程序在不同的tab窗口中实例的互操作。

3. IndexedDB的API大多是异步的:你可以向数据库发出操作的“请求”,当操作完成时会产生一个DOM事件,通过事件的类型会知道操作是否成功。

4. IndexedDB使用“请求”机制:操作对象会接收到DOM的success和failure事件,它也有相应的onsuccess和onerror的属性;对象还有readyState、result和errorCode属性来查看当前“请求”的状态,而result属性则根据不同的“请求”返回不同的结果。

5. IndexedDB 使用DOM事件机制来处理“请求”的结果:DOM事件的type属性提示操作是否成功,target属性指向发生“请求”的对象(大多数情况下是IDBRequest对象)。

6. IndexedDB工作基本模式:

0 创建一个交互操作对象

1 发送操作“请求”

2 通过监听DOM事件等待操作完成

3 处理“请求”结果

二、 打开数据库

IndexedDB的操作对象是以moz开头,如我们打开一个数据库如下:

 

1var request = mozIndexedDB.open("MyTestDatabase");

 

mozIndexedDB对象只有一个open方法,它的参数即为数据库的名称,它返回一个IDBRequest对象。接下来要做的就是为request添加onsuccess和onerror事件的处理,它们分别在返回的DOM事件的type为success和error时调用,

 

01request.onerror = function(event) {
02 
03  // Do something with request.errorCode!
04 
05};
06 
07request.onsuccess = function(event) {
08 
09  // Do something with request.result!
10 
11};

IndexedDB采用最小化的错误事件处理,你不会看到很多类型的错误,它只提供一个错误的事件,可以通过event.target.errorCode来查看错误的信息,通常大多的错误都是用户不允许web操作本地的数据库,远程web所拥有的权限问题。

三、 设置数据库的version

当创建数据库之后,需要添加数据,IndexedDB采用对象存储。首先要检查数据库的版本,若不是所期望的值,就要调用setVerion()方法来设置它的版本,如:

 

01if (db.version != "1.0") {
02 
03  var request = db.setVersion("1.0");
04 
05  request.onerror = function(event) {
06 
07    // Handle errors.
08 
09  };
10 
11  request.onsuccess = function(event) {
12 
13    // Set up the database structure here!
14 
15  };
16 
17}

 

IndexedDB存储的每一个对象均与一个key 关联,关于key 的获取方法参见()。同时我们还可以为对你的存储创建一个Index来查看存储对象部分属性值,如存储人的信息的数据库,我们希望保证不同的人拥有不同的email,就可以使用index和unique flag来设置,如:

 

01// This is what our customer data looks like.
02 
03const customerData = [
04 
05  { ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" },
06 
07  { ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" }
08 
09];
10 
11var request = db.setVersion("1.0");
12 
13request.onerror = function(event) {
14 
15  // Handle errors.
16 
17};
18 
19request.onsuccess = function(event) {
20 
21  // Create an objectStore to hold information about our customers. We're
22 
23  // going to use "ssn" as our key path because it's guaranteed to be
24 
25  // unique.
26 
27  var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
28 
29  // Create an index to search customers by name. We may have duplicates
30 
31  // so we can't use a unique index.
32 
33  objectStore.createIndex("name""name", { unique: false });
34 
35  // Create an index to search customers by email. We want to ensure that
36 
37  // no two customers have the same email, so use a unique index.
38 
39  objectStore.createIndex("email""email", { unique: true });
40 
41  // Store values in the newly created objectStore.
42 
43  for (i in customerData) {
44 
45    objectStore.add(customerData[i]);
46 
47  }
48 
49};

  creatObjectStore()方法和createIndex()方法都有一个可选的对象选项来区分是创建数据库还是索引。creatObjectStore()方法会请求“customers”创建存储对象,并以ssn属性为存储对象的键值,任何试图存储进数据库的对象都需要有ssn属性;我们也可以通name的这个Index来查看存储对象,但对于没有name属性的对象将不会显示出来。

向数据库中添加数据

四、 在添加数据之前,需要先创建一个transaction,创建的方法有三个参数,后两个为可选的,第一个为要关联的数据库名称数组,第二个为打开此数据库的方式(如只读),若无则打开的方式为只读,如:

var transaction = db.transaction(["customers"],IDBTransaction.READ_WRITE);

一个transaction生存时间是与DOM 事件相关联的,如果创建它之后并在返回的事件中没有使用它,就会消亡,唯一让它处理激活状态的就去是使用“请求”机制,当一个请求完成后,在它的回调函数中继续请求,否则transaction就是会消亡。一个transaction有三个事件,为onerror、onsuccess和onabort,一个简单的例子:

 

01// Do something when all the data is added to the database.
02 
03transaction.oncomplete = function(event) {
04 
05  alert("All done!");
06 
07};
08 
09transaction.onerror = function(event) {
10 
11  // Don't forget to handle errors!
12 
13};
14 
15var objectStore = transaction.objectStore("customers");
16 
17for (var in customerData) {
18 
19  var request = objectStore.add(customerData[i]);
20 
21  request.onsuccess = function(event) {
22 
23    // event.target.result == customerData[i].ssn
24 
25  };
26 
27}

 

五、 从数据库中删除数据

删除数据很简单,如下:

 

01var request = db.transaction(["customers"], IDBTransaction.READ_WRITE)
02 
03                .objectStore("customers")
04 
05                .delete("444-44-4444");
06 
07request.onsuccess = function(event) {
08 
09  // It's gone!
10 
11};

 

六、 数据库中取数据

使用get()方法,参数为存储对象的key,如:

 

1db.transaction("customers").objectStore("customers").get("444-44-4444").onsuccess = function(event) {
2 
3  alert("Name for SSN 444-44-4444 is " + event.target.result.name);
4 
5};

 

七、 使用游标

使用get()方法需要知道存储对象的key值,但若不知道key值,要看存储对象,就可以使用游标,如下:

 

01var objectStore = db.transaction("customers").objectStore("customers");
02 
03objectStore.openCursor().onsuccess = function(event) {
04 
05  var cursor = event.target.result;
06 
07  if (cursor) {
08 
09    alert("Name for SSN " + cursor.key + " is " + cursor.value.name);
10 
11    cursor.continue();
12 
13  }
14 
15  else {
16 
17    alert("No more entries!");
18 
19  }
20 
21};

 

openCursor()方法有许多参数,首先你可设置遍历的Key的范围,其次可以设置游标遍历的方向。Continue();表示继续遍历。

八、 使用索引

在数据库中,所有的数据都是以SSN以key值来存储的,若要通过name等其他属性查看存储对象,需要遍历每个SSN并将它的name提取出判断是否为要查看的对象,但可以通过index而更为简单的实现,如:

 

1var index = objectStore.index("name");
2 
3index.get("Donna").onsuccess = function(event) {
4 
5  alert("Donna's SSN is " + event.target.result.ssn);
6 
7};

 

我们还可以通过index使用cursor来遍历存储的数据,并根据不同的cursor打开方式,返回不同的遍历结果,如下两种方式:

 

01index.openCursor().onsuccess = function(event) {
02 
03  var cursor = event.target.result;
04 
05  if (cursor) {
06 
07    // cursor.key is a name, like "Bill", and cursor.value is the whole object.
08 
09    alert("Name: " + cursor.key + ", SSN: " + cursor.value.ssn + ", email: "+ cursor.value.email);
10 
11    cursor.continue();
12 
13  }
14 
15};
16 
17index.openKeyCursor().onsuccess = function(event) {
18 
19  var cursor = event.target.result;
20 
21  if (cursor) {
22 
23    // cursor.key is a name, like "Bill", and cursor.value is the SSN.
24 
25    // No way to directly get the rest of the stored object.
26 
27    alert("Name: " + cursor.key + ", "SSN: " + cursor.value);
28 
29    cursor.continue();
30 
31  }
32 
33};

 

九、 关于游标遍历的范围和方向

如果想要限制游标的遍历范围,可以使用“key range”的对象,并将它做为openCursor()和openKeyCursor()的第一个参数,这样的范围可以是单个键值、或是一个最低边界和最高边界的范围,并规定是否包括范围,如下:

 

01// Only match "Donna"
02 
03var singleKeyRange = IDBKeyRange.only("Donna");
04 
05// Match anything past "Bill", including "Bill"
06 
07var lowerBoundKeyRange = IDBKeyRange.lowerBound("Bill");
08 
09// Match anything past "Bill", but don't include "Bill"
10 
11var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound("Bill"true);
12 
13// Match anything up to, but not including, "Donna"
14 
15var upperBoundOpenKeyRange = IDBKeyRange.upperBound("Donna"true);
16 
17//Match anything between "Bill" and "Donna", but not including "Donna"
18 
19var boundKeyRange = IDBKeyRange.bound("Bill""Donna"falsetrue);
20 
21index.openCursor(boundKeyRange).onsuccess = function(event) {
22 
23  var cursor = event.target.result;
24 
25  if (cursor) {
26 
27    // Do something with the matches.
28 
29    cursor.continue();
30 
31  }
32 
33};

另外,还可以规定游标遍历的方向,默认的是上升的方向,若使用相反的方向,可以将PREV作为openCursor()或是openKeyCursor()的第二个参数,如下:

 

01objectStore.openCursor(null, IDBCursor.PREV).onsuccess = function(event) {
02 
03  var cursor = event.target.result;
04 
05  if (cursor) {
06 
07    // Do something with the entries.
08 
09    cursor.continue();
10 
11  }
12 
13};

 

需要注意的是,在索引中使用游标时,由于可能有多个键值是相同的,这时候总是返回最低边界的那一个对象,为解决此问题,将NEXT_NO_DUPLICATE 或是PREV_NO_DUPLICATE做为它的第二个参数,如下:

 

1index.openKeyCursor(null, IDBCursor.NEXT_NO_DUPLICATE).onsuccess =function(event) {
2  var cursor = event.target.result;
3  if (cursor) {
4    // Do something with the entries.
5    cursor.continue();
6  }
7};

   

 

十、 数据库版本的变化

当web app需要请求数据库的变化时,要考虑用户在一个tab中打开老版本的app,而在另一个tab窗口中打开新版本的app时会发生什么情况,当你调用setVersion()时,所有其它打的数据库必须显示的接受该请求时,你才能对数据库进行更改。

 

01mozIndexedDB.open("MyTestDatabase").onsuccess = function(event) {
02 
03  var db = event.target.result;
04 
05  // If the database is at the correct version then we can skip straight to using it.
06 
07  if (db.version == "1.0") {
08 
09    useDatabase(db);
10 
11    return;
12 
13  }
14 
15  // Check that the database isn't a newer version already.
16 
17  if (db.version != "") {
18 
19    alert("Database has a version which we don't know how to upgrade!");
20 
21    return;
22 
23  }
24 
25  // Otherwise we need to change the version.
26 
27  var request = db.setVersion("1.0");
28 
29  request.onblocked = function(event) {
30 
31    // If some other tab is loaded with the database, then it needs to be closed
32 
33    // before we can proceed.
34 
35    alert("Please close all other tabs with this site open!");
36 
37  };
38 
39  request.onsuccess = function(event) {
40 
41    // All other databases have been closed. Set everything up.
42 
43    db.createObjectStore(/* ... */);
44 
45    useDatabase(db);
46 
47  };
48 
49};
50 
51function useDatabase(db) {
52 
53  // Make sure to add a handler to be notified if another page requests a version
54 
55  // change. We must close the database. This allows the other page to upgrade the database.
56 
57  // If you don't do this then the upgrade won't happen until the user close the tab.
58 
59  db.onversionchange = function(event) {
60 
61    db.close();
62 
63    alert("A new version of this page is ready. Please reload!");
64 
65  };
66 
67  // Do stuff with the database.
68 
69}

 

十一、 使用javascript Generators

注意:这只能在firefox中使用,不支持IE、chrome、Safari

Generators 在firefox中用于简化异步代码,但只能在javascript 1.7及后续的版本上,如:

<script type="text/javascript;version=1.7" src="myScript.js"></script>

myScript.js的内容如下:

 

01// Need to stash the generator in a global variable.
02 
03var generator;
04 
05// Simple event listener function to pass the received event to the generator.
06 
07function grabEvent(event) {
08 
09  generator.send(event);
10 
11}
12 
13// When we're all done we can close the generator, but that must happen outside
14 
15// of the generator so we use a timeout.
16 
17function closeGenerator() {
18 
19  setTimeout(function() {
20 
21    generator.close();
22 
23  }, 0);
24 
25}
26 
27// Our main steps
28 
29function databaseOperation() {
30 
31  mozIndexedDB.open("MyTestDatabase").onsuccess = grabEvent;
32 
33  var event = yield;
34 
35  var db = event.target.result;
36 
37  if (db.version != "1.0") {
38 
39    db.setVersion("1.0").onsuccess = grabEvent;
40 
41    event = yield;
42 
43    var transaction = event.transaction;
44 
45    db.createObjectStore("stuff");
46 
47    transaction.oncomplete = grabEvent;
48 
49    yield;
50 
51  }
52 
53  db.transaction(["stuff"]).objectStore("stuff").get("foo").onsuccess = grabEvent;
54 
55  event = yield;
56 
57  alert("Got result: " + event.target.result);
58 
59  // We're all done.
60 
61  closeGenerator();
62 
63  // Always have an extra yield at the end or you will see StopIteration
64 
65  // exceptions.
66 
67  yield;
68 
69}
70 
71generator = databaseOperation();
72 
73generator.next();

 

十二、 安全性

需要注意的是IndexedDB在以iframe等方式加载到其它网站/网页是是不可运用的。

 

IDBRequest

它反应了向数据库IDBDatabase发出的请求的状况

属性:onsuccess --- 类型为函数,请求成功后执行,参数为请求成功产生的event(IDBSuccessEvent, IDBTransactionEvent)

      Onerror --- 类型为函数,请求出错时执行,参数为错误时的event(IDBErrorEvent)

      readyState --- 请求的状态,“1”为正在执行,“2”为执行完成

示例:

 

1<pre>
2 
3var request = mozIndexedDB.open("MyTestDatabase") ;
4 
5request.onerror = function(event)  {  //handle error   };
6 
7request.onsuccess=function(event) { var db = request.result; //得到数据库对象,或db=event.target.result;  };
8 
9</pre>

IDBSuccessEvent向IndexedDB请求成功后产生的DOM事件属性:使用event.target.result来得到请求成功后返回的结果,参见IDBRequest中示例!

转载于:https://www.cnblogs.com/tingzi/archive/2012/08/07/2626663.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401375.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文章收藏(一)

用 Yarn 你还能做这 5 件事 [译] 在 JavaScript 领域中有几个包管理器: npm&#xff0c;bower&#xff0c;component&#xff0c;和 volo。到本文为止&#xff0c;最受欢迎的包管理器是 npm。npm 客户端提供了对 npm 注册库中成千上万代码的访问。Facebook 推出了一款名叫 Yarn…

前端 进阶

前端 进阶一、HTMLmetaviewport[题] meta标签&#xff0c;实现页面自动刷新/跳转二、CSSCSS选择器CSS选择器匹配原理CSS优先级 / 权重可继承 / 不可继承属性盒模型offsetWidth、clientWidth、scrollWidth**box-sizing属性BFC块级格式化上下文position定位实现水平居中实现垂直居…

Windows文件被占用解决办法

我们有时会遇到某个文件被占用&#xff0c;无法删除或者修改。很多人此时重启机器来解决&#xff0c;但是因为有的程序已启动就把文件占用了&#xff0c;重启也没用。 其实&#xff0c;我们可以使用perfmon.exe /res 在上面的搜索框里输入被占用的文件名&#xff0c;就可以知道…

配置yum,nc,telnet

一、学习中问题   最近学习在学习Hadoop的一个子项目Zookeeper&#xff0c;在测试其中的“四字命令”---”echo ruok|nc localhost 2181“时发现命令无法被识别&#xff0c;如下图所示&#xff1a; [roothadoop ~]# echo ruok|nc localhost 2181 -bash: nc: command not foun…

调用方法mssql_fetch_row、mssql_fetch_array、mssql_fetch_assoc和mssql_fetch_objcect读取数据的区别...

方法名&#xff1a;mssql_fetch_row() 测试&#xff1a; 返回&#xff1a; Notice: Undefined index: UserId in D:/_PHP_Test/Test2/test_connLocalDB.php on line 32 ::王小一Notice: Undefined index: UserId in D:/_PHP_Test/Test2/test_connLocalDB.php on line 32 ::王小…

20145318赵一《网络对抗》后门原理与实践

20145318赵一《网络对抗》后门原理与实践 知识点 后门 后门程序一般是指那些绕过安全性控制而获取对程序或系统访问权的程序方法。  在软件的开发阶段&#xff0c;程序员常常会在软件内创建后门程序以便可以修改程序设计中的缺陷。但是&#xff0c;如果这些后门被其他人知道&…

Nagios:企业级系统监控方案

在大多数情况下Cacti RRDtool已经实现对系统各种参数的监测。但很多企业可能不满足于仅仅监测系统基本参数的需求&#xff0c;而是需要监测除基本参数之外的各种应用程序的运行状况。很显然在这种情况下对于一些系统或者是自定义的程序Cacti RRDtool的局限性就显示出来了。而…

Universal-Image-Loader解析(二)——DisplayImageOptions的详细配置与简单的图片加载...

在使用这个框架的时候&#xff0c;我们必须要配置一个DisplayImageOptions对象来作为ImageLoader.getInstance().displayImage&#xff08;&#xff09;中的参数&#xff0c;所以很有必要讲解这个对象的配制方法。讲解完了后其实这个框架我们就会了解的比较详尽了。 1.默认的配…

React 进阶

React 进阶一、认识 React1、是什么&#xff1f;2、React 特性3、React 第一个实例&#xff08;HTML 模板&#xff09;4、React 安装二、React 核心1、JSX2、元素渲染3、组件4、Props5、State6、组件生命周期7、事件处理8、条件渲染9、列表 & Key10、表单11、状态提升12、组…

dropMenu----简单的下拉菜单生成器

HTML <div class"input-group"><span class"input-group-addon" style"width: 100px" >职级&#xff1a;</span><input type"text" class"units form-control" id"jobTitle" value"其…

linux之Vim使用

Vim同Emac是Linux世界下最为流行的两个文本编辑工具&#xff0c;集中精力学习一个就好了&#xff0c;暂定以Vim为学习对象。在本文中&#xff0c;一些基本的操作将不再介绍&#xff0c;只会介绍最为常用的命令以及设置&#xff0c;操作系统为Ubuntu 12.04. Vim的默认配置&#…

Holedox Moving

2012-08-11 我的第一个A*算法&#xff1a; 四处看A*算法。。还是有一点没有弄明白就是那个当已经在列表中的时候再次进入的时候怎么去更新。 这道题。。有点难开始的时候不会位压缩&#xff0c;去看了一个别人的代码。所以感谢一下。这位高手。写了一个bfs(),500多ms。 看了A*…

mint mvc文件上传功能——使用篇

为什么80%的码农都做不了架构师&#xff1f;>>> 为了不打击大家的积极性&#xff0c;暂时只着重讲用法&#xff0c;原理方面暂时不讲太多。 配置web.xml 文件上传需要用到servlet3的异步处理功能。需要在web.xml配置文件中加入异步支持声明&#xff08;注释处&am…

React 项目开发问题积累

React 开发问题积累1. 修改antd的组件样式2. antd级联选择框&#xff08;后台数据渲染&#xff09;1. 修改antd的组件样式 问题&#xff1a;直接修改样式好像不起作用&#xff0c;直接在组件上加style行内样式也不生效 方案&#xff1a;用 :global样式穿透 全局样式直接使用 …

关于spring中util:/的配置

解决redis设置缓存时间找到的帖子&#xff0c;我这个初学者需要学习的还是很多的。 原文地址&#xff1a;http://www.doc100.net/bugs/t/216322/index.html 探索<util/>命名空间 事情的发展总是一段曲折前进的过程。当Spring刚出现时&#xff0c;开发者可以使用<…

静态类

静态类必须直接从System.Object派生&#xff0c;从其他任何基类派生没有任何意义。无法创建静态类的实例静态类不能实现任何接口&#xff0c;这是因为只有使用类的一个实例时&#xff0c;才可以调用类的接口方法静态类只能定义静态成员&#xff08;字段、方法、属性和事件&…

ASP.NET 数据库缓存依赖

By Peter A. Bromberg, Ph.D. 在ASP.NET中&#xff0c;Cache类最酷的特点是它能根据各种依赖来良好的控制自己的行为。以文件为基础的依赖是最有用的&#xff0c;文件依赖项是通过使用 Cache.Insert 并提供引用文件的 CacheDependency 对象添加的 Cache.Insert("MyData&qu…

React Router路由详解

React Router路由详解一、基础1、安装使用2、React Router 中通用的组件路由组件 BrowserRouter 和 HashRouter路径匹配组件: Route 和 Switch导航组件: Link 和 NavLinkRedirect 重定向withRouter编程式导航 - history 对象路由过渡动画打包部署的路由配置3、路由配置实例一、…

TLS 1.2详解

TSL由多个协议组成的两层协议集合&#xff0c;工作与应用层和传输层之间。 TLS协议包含两层协议&#xff1a;记录层协议&#xff08;TLS Record Protocol协议&#xff09;和 握手协议&#xff08;TLS Handshake Protocol协议&#xff09;&#xff0c;底层采用可靠传输协议&…

个人作业2——英语学习APP案例分析

第一部分 调研&#xff0c; 评测 1.下载并使用&#xff0c;描述最简单直观的个人第一次上手体验&#xff1a; 没有各种广告&#xff0c;界面简洁&#xff0c;软件安装包略小于其他翻译软件。就内存的占用而言优于同款热门软件有道词典。 2.必应词典&#xff08;Android客户端&a…