使用indexedDB(二)(翻译)

插入、查询、删除数据

在您对新建的数据库做任何操作之前,需要开启一个事务。事务源自数据库对象,您必须指定事务要涵盖的对象store。一旦进入事务,您就能够访问对象store,用以操作数据和创建请求。接下来,您需要决定是更改数据库还是读取数据库的内容。事务有三个有效模式:只读,读写,版本变更。

变更数据库模式或者结构——牵涉到创建或者删除对象store或者index——必须让事务处于版本变更versionchange模式。通过呼叫IDBFactory.open并指定版本号来打开该事务。(Webkit浏览器,没有完善最新的IndexedDB版本,IDBFactory.open只能携带一个参数:数据库名字;那么您必须呼叫IDBVersionChangeRequest.setVersion来建立versionchange事务)。

为了读取对象store中的记录,事务可以使用readonly模式或者readwrite模式。如果要更改记录,事务必须处于readwrite模式。您通过呼叫IDBDatabase.transaction()函数来打

事务,该函数接受两个参数, storeNames(作用域,定义为您将要访问的对象store类型数组),模式mode(readonly或者 readwrite)。该函数返回事务对象,该对象包含DBIndex.objectStore方法,您可以用它访问对象store。默认地,事务以readonly模式打开。

注意:从firefox40开始,IndexedDB事务为了提高性能已经放宽了durability。以前,在读写事务中,只有当所有数据

都已写入磁盘时,才会触发IDBTransaction.oncomplete。在firefox40及更高的版本中,操作系统被告知开始写数据之后,但是隐含地,在数据完全写入磁盘之前,oncomplete事件就会被触发。

为事务正确设置作用域和模式,可以提高数据访问性能,要点如下:

定义作用域时,只指定您需要的对象store,这样,您就可以同时无重叠(scope)地运行多个事务

只在必要时指定读写readwrite模式。您可以同时重叠(scope)地运行多个readonly事务,但是只能为一个对象store运行readwrite事务。

插入数据

如果您新建的数据库,您可能想写入数据。如下所示:

var transaction = db.transaction(["customers"], "readwrite");
// Note: Older experimental implementations use the deprecated constant IDBTransaction.READ_WRITE instead of "readwrite".
// In case you want to support such an implementation, you can write:
// var transaction = db.transaction(["customers"], IDBTransaction.READ_WRITE);

transaction()函数有两个参数,并返回一个transaction对象。第一个参数是事务涵盖的对象store列表,(即事务的scope)。

如果您想让事务涵盖所有的对象store,您可以在此处指定一个空数组,但是请不要那样做,因为规范说了,空数组将引发 InvalidAccessError错误。如果您不指定第二个参数,默认地将使用read-only模式。如您想写数据库,请指定为readwrite。

现在您创建了事务,您需要了解它的生存期。事务与事件循环绑定的非常紧密。如果您创建了事务并返回给事件循环,

然而并没有使用,那么事务将变成非活动状态。让事务保持活动状态的唯一方法是在其上创建一个请求。当请求完成时,

您将得到一个DOM事件,将定请求是成功的,您将有新的机会在回调函数中扩展事务。如果您没有扩展事务就返回给了事务循环,事务将变成非活动状态,以此类推。只要存在等待期pending的请求,事务将保持活动状态。事务的生存期确实很简单,但是要掌握它还是需要一些时间的。更多一些例子,也会有助于理解。如果您已经开始阅读

TRANSACTION_INACTIVE_ERR错误码,就不合适了(因为还没理解事务的生存期)。

事务可以分为三种类型的DOM事件:error,abort,和complete。我们已经讨论了error事件的冒泡方式,因此,事务接受任何从它产生的请求抛出的error事件。更微妙的是,

error事件的默认行为是中止它所在的事务。除非您在错误处理中先调用stopPropagation()再执行其它处理,否则事务将回滚。这样的设计可以强制要求考虑和处理错误,但是

如果错误处理太冗长、琐碎,您可以在数据库对象上绑定一个错误处理。如果您没有处理错误事件,或者在事务上呼叫了Abort()函数,事务将回滚,事务的回滚事件将被触发。

或者,所有的等待期pending的请求都被处理完。您将得到一个Complete事件。如果您执行大量的数据库操作,那么跟踪事务而不是单个的请求,将有助于您理清思路。

现在您有事务了,您需要从中获取对象store。事务只是让您拥有当初创建事务时指定的那个对象store。然后您可以向对象store中添加数据了。

// Do something when all the data is added to the database.
transaction.oncomplete = function(event) {
  alert("All done!");
};

transaction.onerror = function(event) {
  // Don‘t forget to handle errors!
};

var objectStore = transaction.objectStore("customers");
for (var i in customerData) {
  var request = objectStore.add(customerData[i]);
  request.onsuccess = function(event) {
    // event.target.result == customerData[i].ssn;
  };
}

呼叫add()方法产生的请求结果是被添加的【键】的值。在此情况下,它应该等于被添加对象的ssn属性,因为对象store
使用ssn属性作为keypath。注意,add()方法要求在数据库中不能存在相同【键】的对象。如果您试图更改一个已存在的对象,或者您不关心是否存在该对象,您可以呼叫put()方法,如 Updating an entry in the database中所示。

删除数据

删除数据很简单:

var request = db.transaction(["customers"], "readwrite")
                .objectStore("customers")
                .delete("444-44-4444");
request.onsuccess = function(event) {
  // It‘s gone!
};

查询数据

既然数据库中已经有数据了,您可以通过几种方法查询数据。首先,最简单的get()方法。您需要提供【key】来查询数
据,就像这样:

var transaction = db.transaction(["customers"]);
var objectStore = transaction.objectStore("customers");
var request = objectStore.get("444-44-4444");
request.onerror = function(event) {
  // Handle errors!
};
request.onsuccess = function(event) {
  // Do something with the request.result!
  alert("Name for SSN 444-44-4444 is " + request.result.name);
};

对于一个“简单”查询来说,代码还是有点多啊。这里您可以让它更缩短一些,假定您在数据库层面处理了错误消息:

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

看看它是如何工作的?因为只有一个对象store,您不用传递对象store列表,而只把对象store的名字给事务。而且,
您只是查询数据库,所以您不需要readwrite模式。呼叫transaction()方法默认的模式就是readonly。另一个微妙之处
在于您没有真正的把请求保存到一个变量。因为DOM事件把该请求request作为它的target,您可以使用event.target替代request。

注意,通过限制事务的作用域scope,和事务的模式,可以提高数据访问速度。

更新数据
现在我们查询到一些数据,更新它并插入IndexedDB数据库也很简单。我们把前面的例子改一下:

var objectStore = db.transaction(["customers"], "readwrite").objectStore("customers");
var request = objectStore.get("444-44-4444");
request.onerror = function(event) {
  // Handle errors!
};
request.onsuccess = function(event) {
  // Get the old value that we want to update
  var data = event.target.result;

  // update the value(s) in the object that you want to change
  data.age = 42;

  // Put this updated object back into the database.
  var requestUpdate = objectStore.put(data);
   requestUpdate.onerror = function(event) {
     // Do something with the error
   };
   requestUpdate.onsuccess = function(event) {
     // Success - the data is updated!
   };
};

在这里我们创建一个objectStore,请求读出一个数据记录,使用【键】值ssn:444-44-4444。然后把查询结果存放在
变量data中,更改变量data的age属性值,再创建一个请求,把更改过的数据写回数据库,覆盖原来的结果。

注意:此时,我们必须指定readwrite模式的事务,因为要写入数据库内容,而不只是查询数据

时间: 2024-08-27 17:40:15

使用indexedDB(二)(翻译)的相关文章

关系型数据库工作原理-事务管理(二)(翻译自Coding-Geek文章)

本文翻译自Coding-Geek文章:< How does a relational database work>. 原文链接:http://coding-geek.com/how-databases-work/#Buffer-Replacement_strategies 紧接上一篇文章,本文翻译了如下章节: 一. Log manager(日志管理) 通过前面的章节,我们已经知道,为了提升性能,数据库会将数据缓存在内存中.但是,如果在事务提交过程中,数据库服务器崩溃了.缓存在内存的数据就会丢失

vim中Mapping already in use: &quot;&lt;LocalLeader&gt;is&quot;, mode &quot;n&quot;错误解决的方法解释

出现上面问题的原因是 c-support 和 a.vim 的插件冲突了,你只要将 a.vim 的两行代码注释掉就可以了 链接 英文:这里一,这里二 翻译:这里 操作截图:前提: 使用vundle管理插件

十五年学不会英语的原因

学习前预热: ---轻松学英语第一步:建立英语思维    为什么大家学英语学得这么累,最后依然对英语糊糊涂涂?原因只有一个--就是我们的学习能力太差了!!我们的老师太笨了!!!    这篇文章主要是给大家讲英语的基本结构, 看了这篇文章,你们会突然就明白,英语怎么会如此简单!!    首先我们来看下面这两张地图(左边是中国地图,右边是英国地图):?    例如,我们中国人一见面第一句话是--"你吃了吗."英国人一见面的第一句话是--"今天天气怎么样? what's the w

转:【15年学不会英语的原因】

学习前预热:———轻松学英语第一步:建立英语思维 为什么大家学英语学得这么累,最后依然对英语糊糊涂涂?原因只有一个——就是我们的学习能力太差了!!我们的老师太笨了!!! 这篇文章主要是给大家讲英语的基本结构, 看了这篇文章,你们会突然就明白,英语怎么会如此简单!! 首先我们来看下面这两张地图(左边是中国地图,右边是英国地图): 例如,我们中国人一见面第一句话是——“你吃了吗.”英国人一见面的第一句话是——“今天天气怎么样? what’s the weather like?为什么中国人一见面就问:

indexedDB 基本概念(翻译)

IndexedDB是可以让您在浏览器中持久保存数据的一种方法.不管网络是否可用,它都可以让您创建带有强大的数据查询能力的web应用,这些应用可以是联网的.或者离线的.IndexedDB 适用于存储大量数据的应用(比如dvd碟片出租库的登记簿)和不需要持久连网运行的应用(比如,邮件客户端.待办事项.注释板) 关于 本文档讨论IndexedDB的核心概念和术语.将为你展示重点并解释关键的概念 下面是一些有用的提示信息: 如需学习更多的IndexedDB 术语,请参考Definitionssectio

[翻译] ORMLite document -- How to Use Part (二)

前言 此文档翻译于第一次学习 ORMLite 框架,如果发现当中有什么不对的地方,请指正.若翻译与原文档出现任何的不相符,请以原文档为准.原则上建议学习原英文文档. ---------------------------------------------------------------------------------------------- 二.如何使用 2.7 表的创建 ORMLite 提供了一些工具类为您存储在数据库中的类创建 table 和 schema. 2.7.1 Tabl

[翻译]NUnit---TearDown and SetUpFixture and Test Attributes(二十)

TearDownAttribute (NUnit 2.0 / 2.5) 本特性在TestFixture内部使用,每个测试方法执行后调用的方法集.也可以在SetUpFixture中使用,在同一命名空间或者程序集种相同的功能. NUnit2.5之前,类只能有一个TearDown方法且必须是示例方法. 从NUnit2.5开始,TearDown方法可以使静态或者示例方法,也可以在一个夹具中定义多个TearDown方法.通常多个TearDown方法只会在不同层级的继承中定义. 如果所有SetUp方法都正确

[翻译]NUnit---TestCase Attributes(二十一)

TestCaseAttribute (NUnit 2.5) TestCase特性有两个效果,包括标记一个方法使用参数并且在调用的时候提供内置数据.示例如下,本示例会使用不同数据集执行3次: [TestCase(12,3,4)] [TestCase(12,2,6)] [TestCase(12,4,3)] public void DivideTest(int n, int d, int q) { Assert.AreEqual( q, n / d ); } Note:.net特性的限制了参数类型,N

python网络爬虫入门(二)——用python简单实现调用谷歌翻译

最近在看国外的文档,有些生词不认识.就用谷歌翻译来理解,用着用着闲来无事就按F12查看了下页面的源代码.发现可以用python简单的实现下谷歌翻译的页面功能.于是先上网搜下有没有类似的文章博客,发现几篇不错的,于是参考其他代码与自己的思路,简单的实现了下翻译的功能,代码如下: import re import urllib,urllib2 #----------模拟浏览器的行为,向谷歌翻译发送数据,然后抓取翻译结果,这就是大概的思路------- def Gtranslate(text): #t