现在我们已经有了一个事务,我们需要理解它的生命周期。事务和事件循环的联系非常密切。如果你创建了一个事务但是并没有使用它就返回给事件循环,那么事务将变得无效。保持事务活跃的唯一方法就是在其上构建一个请求。当请求完成时你将会得到一个 DOM 事件,并且,假设请求成功了,你将会有另外一个机会在回调中来延长这个事务。如果你没有延长事务就返回到了事件循环,那么事务将会变得不活跃,依此类推。只要还有待处理的请求事务就会保持活跃。事务生命周期真的很简单但是可能需要一点时间你才能对它变得习惯。还有就是来几个例子也会有所帮助。如果你开始看到TRANSACTION_INACTIVE_ERR 错误代码,那么你已经把某些事情搞乱了。
var objectStore = db.transaction("customers").objectStore("customers");
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
alert("Name for SSN " + cursor.key + " is " + cursor.value.name);
cursor.continue();
}
else {
alert("No more entries!");
}
};
openCursor() 函数需要几个参数。首先,你可以使用一个 key range 对象来限制被检索的项目的范围。第二,你可以指定你希望进行迭代的方向。在上面的示例中,我们在以升序迭代所有的对象。游标成功的回调有点特别。游标对象本身是请求的result (上面我们使用的是简写形式,所以是 event.target.result)。然后实际的 key 和 value 可以根据游标对象的key 和 value 属性被找到。如果你想要保持继续前行,那么你必须调用游标上的 continue() 。当你已经到达数据的末尾时(或者没有匹配openCursor() 请求的条目)你仍然会得到一个成功回调,但是 result 属性是 undefined。
使用游标的一种常见模式是提取出在一个对象存储空间中的所有对象然后把它们添加到一个数组中,像这样:
var customers = [];
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
customers.push(cursor.value);
cursor.continue();
}
else {
alert("Got all customers: " + customers);
}
};
警告: 下面的函数并不是 IndexedDB 标准的一部分!
Mozilla 也已经实现了 getAll()来处理这种情况。它不是 IndexedDB 标准的一部分,所以它未来可能会消失。我们已经把它包含在这里是因为我们觉得它比较有用。下面的代码实现的是跟上面同样的事情:
如果你想要限定你在游标中看到的值的范围,你可以使用一个 key range 对象然后把它作为第一个参数传给 openCursor() 或是openKeyCursor()。你可以构造一个只允许一个单一 key 的 key range,或者一个具有下限或上限,或者一个既有上限也有下限。边界可以是闭合的(也就是说 key range 包含给定的值)或者是“开放的”(也就是说 key range 不包括给定的值)。这里是它如何工作的:
// 只匹配 "Donna"
var singleKeyRange = IDBKeyRange.only("Donna");
// 匹配所有在 "Bill" 前面的, 包括 "Bill"
var lowerBoundKeyRange = IDBKeyRange.lowerBound("Bill");
// 匹配所有在 “Bill” 前面的, 但是不需要包括 "Bill"
var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound("Bill", true);
// Match anything up to, but not including, "Donna"
var upperBoundOpenKeyRange = IDBKeyRange.upperBound("Donna", true);
//Match anything between "Bill" and "Donna", but not including "Donna"
var boundKeyRange = IDBKeyRange.bound("Bill", "Donna", false, true);
index.openCursor(boundKeyRange).onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
// Do something with the matches.
cursor.continue();
}
};
objectStore.openCursor(null, IDBCursor.prev).onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
// Do something with the entries.
cursor.continue();
}
};
index.openKeyCursor(null, IDBCursor.nextunique).onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
// Do something with the entries.
cursor.continue();
}
};
当一个 web app 在另一个标签页中被打开时的版本变更
当你的 web app 在这样一种方式下改变你的数据库时碰到被要求进行版本变化,你需要考虑如果用户已经在一个标签页中打开了你的应用的旧版本的数据库,然后他又在另一个标签页中加载了你的应用的新版本,这种情况下会发生什么事情。当你带着比数据库实际版本更高的版本号调用open() 时,所有其他打开的数据库必须在你开始实际对数据库进行修改之前显式通知这个请求。这里是它如何工作的:
var openReq = mozIndexedDB.open("MyTestDatabase", 2);
openReq.onblocked = function(event) {
// 如果其他标签页已经加载了这个数据库,那么
// 在我们可以继续处理之前它需要被关闭。
alert("Please close all other tabs with this site open!");
};
openReq.onupgradeneeded = function(event) {
// 所有其它数据库都已经被关掉了。Set everything up.
db.createObjectStore(/* ... */);
useDatabase(db);
}
openReq.onsuccess = function(event) {
var db = event.target.result;
useDatabase(db);
return;
}
function useDatabase(db) {
// 确保添加一个如果另一个页面请求一个版本变化时来被通知的处理程序。
// 我们必须关闭这个数据库。这就允许其他页面对数据库进行升级。
// 如果你不这么做的话,除非用户关闭标签页否则升级就不会发生。
db.onversionchange = function(event) {
db.close();
alert("A new version of this page is ready. Please reload!");
};
// 其他针对数据库的处理
}
原题链接:#137 Single Number II
要求:
给定一个整型数组,其中除了一个元素之外,每个元素都出现三次。找出这个元素
注意:算法的时间复杂度应为O(n),最好不使用额外的内存空间
难度:中等
分析:
与#136类似,都是考察位运算。不过出现两次的可以使用异或运算的特性 n XOR n = 0, n XOR 0 = n,即某一
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, det