在 indexedDB API 中,所有针对数据的操作都只能在一个事务中被执行。 indexedDB 提供 3 类事务模式,简单说明如下
为由一些对象仓库名组成的一个字符串数组,用于定义事务的作用范围,即限定该事务中所运行的读写操作只能针对哪些对象仓库进行,当事务中的数据存取操作只针对某个对象仓库进行时
默认的事务模式为 readonly 。用户可在任何给定时刻内打开多个并发的 readonly 事务,但只能打开一个 readwrite 事务。出于此原因,只有在数据更新时才考虑使用 readwrite 事务。单独的(表示不能打开任何其它并发事务) versionchange 事务操作一个数据库或对象存储。可以在 onupgradeneeded 事件处理函数中使用 versionchange 事务创建、修改或删除一个对象仓库,或者将一个索引添加到对象仓库。
在 indexedDB API 中,使用某个已建立连接的数据库对象的 transaction() 方法可以开启事务。例如,要在 readwrite 模式下为 employees 对象仓库创建一个事务∶
var transaction = db.transaction('employees', 'readwrite');
transaction() 方法包含两个参数,具体介绍如下 :
数据库的 objectStoreNames 属性值为由该数据库中的所有对象构成的数组,再将其作为 transaction() 方法的第一个参数值时,可以针对数据库一个仓库进行数据的存取操作。
transaction() 方法返回一个 IDBTransaction 对象,代表被开启的事务。
如果不想限定事务只针对哪些对象仓库进行,那么可以使用数据库的 objectStoreNames 属性值来作方法的第—个参数值,代码如下所示∶
var transaction = db.transaction(idb.objectStoreNames, 'readwrite');
在将数据库的 objetStoreNames 属性值作为 transaction() 方法的第一个参数值,将 "readwrite" 常量值作 transaction() 方法的第二个参数值,运行 transaction() 方法之后,虽然在接下来的代码中可以不必再注意事务对哪些对象仓库进行,以及事务为只读事务,还是读写事务,但是这种做法将对事务在运行时的性能产生很的不利影响。考虑到运行时的性能,建议应该正确指定事务的作用范围,以及事务的读写模式。
在 indexedDB API 中,可以同时运行多个作用范围不重叠的读写事务,如果数据库中存在 storeA 和 storeB 两个对象仓库,事务 A 的作用范围为 storeA ,事务 B 的作用范围为 storeB ,那么可以同时运行事务 A 和事务 B 。如果将事务 A 的作用范围修改为同时包括 storeA 和 storeB 两个对象仓库,且先运行事务 A ,那么事务 B 必须等到事务 A 运行结束后才能运行。即使事务 A 为只读事务,仍然可以同时运行事务 A 和事务 B 。
在 indexedDB API 中,用于开启事务的 transaction() 方法必须被书写到某一个函数中,而且该事务将在函数结束时被自动提交,所以不需要显式调用事务的 commit() 方法来提交事务,但是可以在需要的时候显式调用事务的 abort() 方法来中止事务。
可以通过监听事务对象的 oncomplete 事件(事务结束时触发)和 onabort 事件(事务中止时触发),并定义事件处理函数来定义事务结束或中止时所要执行的处理。
var t = db.transaction(idb.objectStoreNames, 'readwrite');
t.oncomplete = function (event) {
// 事务结束时要执行的处理
};
t.onabort = function (event) {
// 事务终止时将要的处理
};
transaction.abort();