我第一次尝试使用indexedDB,尝试按照我在Internet上找到的各种示例。它有点起作用,但是当我读取数据库时,我得到的结果不一致。
数据库创建如下:
myapp.indexedDB.open = function() {
var request = indexedDB.open('todos', "2");
request.onblocked = function(e) {
alert('Please close all other tabs with this site open so the database can be updated.');
};
request.onsuccess = function(e) {
myapp.indexedDB.db = e.target.result;
myapp.indexedDB.db.onversionchange = function(e) {
myapp.indexedDB.db.close();
alert('The database is being upgraded. Please reload.');
};
myapp.indexedDB.getAllTodoItems();
};
request.onupgradeneeded = function(e) {
var db = e.target.result;
if(!db.objectStoreNames.contains('todo')) {
var store = e.currentTarget.result.createObjectStore(
'todo',
{keyPath: "timeStamp"}
);
}
if(!db.objectStoreNames.contains('sites')) {
var site_store = e.currentTarget.result.createObjectStore(
'sites',
{keyPath: 'id'}
);
}
};
request.onfailure = myapp.indexedDB.onerror;
};
todo商店来自我发现的一个例子。这是我遇到困难的网站商店。
我像这样阅读网站商店:
function update_sites() {
$('#sites_table').ig_grid('delete_all_rows');
var db = myapp.indexedDB.db;
var trans = db.transaction(["sites"], "readwrite");
var store = trans.objectStore('sites');
var cursorRequest = store.openCursor();
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(!!result == false) return;
render_site(result.value);
console.log('rendered a site');
result.continue();
};
cursorRequest.onerror = myapp.indexedDB.onerror;
}
function render_site(site) {
$('#sites_table').ig_grid('add_row', [site.id,site.id,site.flag,site.site_code,site.site_name,site.owner_name,site.address,site.hive_capacity,site.hive_count,render_status(site.status_id)]);
}
到目前为止,一切都很顺利。写入数据库的数据将被正确读取和呈现。
更新数据库时出现问题。更新完成如下:
function sync_sites() {
display_status('');
var jqxhr = $.ajax({
type: "GET",
url: '/myapp.pl/REST/sites'
})
.fail(function(jqXHR, textStatus) {
display_status(jqXHR.responseText);
})
.done(function(data, textStatus, jqXHR) {
var sites = jQuery.parseJSON(data.data);
for (var i = 0; i < sites.length; i++) {
myapp.indexedDB.add_site(sites[i]);
}
alert('sync done');
});
}
myapp.indexedDB.add_site = function(site) {
var db = myapp.indexedDB.db;
var trans = db.transaction(["sites"], "readwrite");
var store = trans.objectStore('sites');
var request = store.put(site);
request.onsuccess = function(e) {
// TODO: whatever is appropriate if the site is added successfully
};
request.onerror = function(e) {
console.log(e.value);
};
};
数据库的更新也会成功。
问题是数据库更新开始后不久 - 在显示'sync done'警告之后,update_sites函数清空显示的站点表并且不添加任何站点:就像数据库是空的一样。然后,如果我继续重新加载站点显示,在几秒钟(几次重新加载)之后,几百到几千行被添加到站点表中,每行重复几次。通常情况下,网站商店/表中有216条记录。最后,关于上次数据库更新(put)完成的时间(我认为),显示更新再次正常工作。
显示更新(update_sites)在大多数情况下都能正常工作 - 如果我在sync_sites运行后的几秒钟的短暂间隔内运行它,它只会得到不正确的结果。
有两种错误模式:第一种,没有数据从商店读取,就好像它是空的或光标没有匹配的记录(从未成功);并且在第二个游标中,当游戏中的所有记录都被返回后,游标不会停止,它会一遍又一遍地循环遍历所有记录,直到最终在一些看似任意的点停止。
我在错误控制台中看不到任何错误,无论是在update_sites正确运行时还是在提供不正确的结果时,还是在sync_sites中。事实上,当它运行时,错误控制台中根本没有错误或警告。
我已经使用sqlite3检查了底层数据库,并且我可以看到数据库中没有重复的记录。 object_data中有219条记录:3条与todo商店相关,216条与网站商店相关。
FWIW,这是Firefox 16.0.1。
我做错了吗?
我是否可以启用其他可能有助于查明错误原因的错误,警告,跟踪或诊断?
还有其他人看到过这种行为吗?
谢谢, 伊恩
答案 0 :(得分:3)
由于IndexedAPI alert('sync done');
的异步性质不正确,因为IDBRequest onsuccess
处理程序并不意味着它已成功添加。只有IDBTransaction的oncompeleted
处理程序才能确保它已添加并准备好查询记录。
此外,您应该使用单个事务来存储记录。 myapp.indexedDB.add_site
应为myapp.indexedDB.add_sites(sites, callback)
,以便循环播放记录。当oncompeleted
它调用回调时。
编辑:添加add_sites功能。
myapp.indexedDB.add_sites = function(sites, callback) {
var db = myapp.indexedDB.db;
var trans = db.transaction(["sites"], "readwrite");
trans.oncompleted = callback;
var store = trans.objectStore('sites');
var put = function(i) {
var request = store.put(sites[i]);
request.onsuccess = function(e) {
i--;
if (i >= 0) put(i);
};
request.onerror = function(e) {
console.log(e.value);
};
};
put(sites.length - 1);
};