Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

indexedDB(叁) 事务机制

  事务机制也算不上什么稀奇的东西,WebSQL也通过事务机制操作的。但是indexedDB的事务机制很特别,它不是通过回调函数处理的,而是按照当前执行的同步代码来作为事务的作用域。这东西稍微有点创新,不过看下例子也很容易理解的。
  我们先来一段最简单的测试代码,看括之前的两篇,这个代码不需要注释也能理解 <input type="button" value="写入" id="btn" />
<script>
window.indexedDB=window.indexedDB||window.webkitIndexedDB;
var cn,db;
cn=indexedDB.open("MyDB",1);
cn.onupgradeneeded=function(e){
  db=e.target.result;
  db.createObjectStore("MyOBJ",{autoIncrement:true});
};
cn.onsuccess=function(e){
  db=e.target.result;
};
btn.onclick=function(){
  var myOBJ=db.transaction(["MyOBJ"],"readwrite").objectStore("MyOBJ");
  myOBJ.add({});
};
</script>
  看完这个代码,你是不是会想,为什么不把myOBJ也定义为全局变量呢?我一开始也是这么想的。你可以试着把代码这么改 var myOBJ;
cn.onsuccess=function(e){
  db=e.target.result;
  myOBJ=db.transaction(["MyOBJ"],"readwrite").objectStore("MyOBJ");
};
btn.onclick=function(){
  myOBJ.add({});
};
  看似逻辑很合理,但是改成这样后,点击“添加”按钮就会出错。 Uncaught Error: TransactionInactiveError: DOM IDBDatabase Exception 7   这就是因为事务的生存周期已经过了,再执行事务中设置的对象就没有权限了。这个代码中,我们的事务是在数据库打开成功的事件中开始的。而这个事件运行结束后同步执行的代码就已经结束了,主线程被返回给浏览器,这样一个事务的生存周期也就结束了。这是我们点下按钮就会出现上面这个错,因为事务已经运行结束了。我们可以在这里给事务加上个执行完成的事件来测试。 cn.onsuccess=function(e){
  db=e.target.result;
  var trans=db.transaction(["MyOBJ"],"readwrite");
  trans.oncomplete=function(){
    console.log("事务已执行完成");
  };
  myOBJ=trans.objectStore("MyOBJ");
  console.log("到这里事务还没执行完成");
};

  这个代码就是在创建事务的那个事件运行结束后调用事务的完成事件,当代码执行到事务所在事件的最后一句时事务都还在运行。因为这个性质,所以我们无法把整个事务对象或者事务里的存储对象定位为全局对象。由于每次要创建事务很麻烦,所以我在最初的那篇“indexedDB的基本操作”中自定义了个doTransaction方法来创建事务并执行代码。但是那篇文章里我只是做了非常简单的定义,如果需要更复杂的事务操作,就需要定义更复杂的方法。比如昨天的那篇“indexedDB的存储对象结构设计”用到了多个存储对象的同时操作,这时候如果有很多个地方用到存储对象的操作句应该定义更复杂的方法来操作。
  除了数据库的事务有这样的机制以外,在indexedDB中只要是事务的东西都有这样的机制,比如删除存储对象。 cn.onsuccess=function(e){
  db=e.target.result;
  db.deleteObjectStore("MyOBJ");
};
  这个代码尝试在数据库链接完成后删除存储对象,运行会抛出一个错误 Uncaught Error: InvalidStateError: DOM IDBDatabase Exception 11   和前面的原因差不多,因为这个删除存储对象的操作必须在数据库初始化的事务中执行。虽然数据库初始化这个事件并没有强调自己是一个事务,但是确实如此。 cn.onupgradeneeded=function(e){
  db=e.target.result;
  //创建两个存储对象
  db.createObjectStore("TAB1");
  db.createObjectStore("TAB2");
  //删除TAB1这个存储对象
  db.deleteObjectStore("TAB1");
};
  这样删除就能成功(不要吐槽例子的SB= =。。),好啦,事务机制大概就是这样,今天先到这儿吧~

参考:
  https://developer.mozilla.org/en-US/docs/IndexedDB/Using_IndexedDB
  http://msdn.microsoft.com/en-us/library/windows/apps/hh466139.aspx
网名:
54.144.24.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^