インターネットで見つけたさまざまな例に従って、indexedDB を初めて試しています。多少は機能しますが、データベースを読み取ると一貫性のない結果が得られます。
データベースは次のように作成されます。
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);
};
};
データベースの更新も成功します。
問題は、データベースの更新が開始された直後、つまり「同期完了」アラートが表示された直後に、update_sites 関数が表示されたサイトのテーブルを空にし、サイトを追加しないことです: データベースが空であるかのように。次に、サイトの表示をリロードし続けると、さらに数秒 (数回リロード) した後、数百から数千の行がサイト テーブルに追加され、各行が数回複製されます。通常、サイトのストア/テーブルには実際には 216 のレコードがあります。最終的に、最後のデータベースの更新 (put) が完了する頃 (と思う) に、表示の更新が再び正しく機能するようになります。
表示更新 (update_sites) は、ほとんどの場合正しく機能します。sync_sites の実行後、数秒という短い間隔で実行すると、正しくない結果しか得られません。
2 つのエラー モードがあります。最初のモードでは、ストアからデータが読み取られず、ストアが空であるか、カーソルがレコードに一致しなかったかのように扱われます (成功したことはありません)。次に、ストア内のすべてのレコードが返された後もカーソルが停止せず、すべてのレコードを何度も繰り返しループし続け、最終的に一見任意のポイントで停止します。
update_sites が正しく実行されたとき、または誤った結果が返されたとき、または sync_sites からのいずれの場合でも、エラー コンソールにエラーは表示されません。実際、これが実行されているとき、エラー コンソールにエラーや警告はまったく表示されません。
基礎となるデータベースを sqlite3 で検査しましたが、データベースにレコードの重複はありません。object_data には 219 のレコードがあり、そのうち 3 つは todo ストアに関連し、216 は sites ストアに関連しています。
FWIW、これは Firefox 16.0.1 です。
私は何か間違ったことをしていますか?
エラーの原因を特定するのに役立つ、有効にできる追加のエラー、警告、トレース、または診断はありますか?
他の誰かがこの動作を見たことがありますか?
ありがとう、イアン