为什么在连接到indexedDB时,onsuccess有时会在onupgradedneed之前被调用
Why does onsuccess sometimes get called before onupgradeneeded when connecting to indexedDB?
我在使用IndexedDB时遇到问题。在Firefox 18上,当我创建一个新数据库时,onsuccess
方法被调用,同时具有onupgradeneeded
。在Chrome24上(这是我想要得到的行为),只有在onupgradeneeded
方法完成之后才会调用onsuccess
方法。
根据IndexedDB上的MDN信息,我的印象是,当调用onsuccess方法时,使用数据库是安全的,但这使得它似乎不在Firefox中。
(function(){
app = {};
// These will hold the data for each store.
app.objectstores = [
{ name: 'UNIVERSITIES',
keyPath: 'UID',
autoIncrement: false,
data_source: 'http://mysites.dev/nddery.ca_www/larelance/data/universite.json' },
];
// Some information pertaining to the DB.
app.indexedDB = {};
app.indexedDB.db = null
app.DB_NAME = 'testdb';
app.DB_VERSION = 1;
/**
* Attempt to open the database.
* If the version has changed, deleted known object stores and re-create them.
* We'll add the data later.
*
*/
app.indexedDB.open = function() {
// Everything is done through requests and transactions.
var request = window.indexedDB.open( app.DB_NAME, app.DB_VERSION );
// We can only create Object stores in a onupgradeneeded transaction.
request.onupgradeneeded = function( e ) {
app.indexedDB.db = e.target.result;
var db = app.indexedDB.db;
// Delete all object stores not to create confusion and re-create them.
app.objectstores.forEach( function( o ) {
if ( db.objectStoreNames.contains( o.name ) )
db.deleteObjectStore( o.name );
var store = db.createObjectStore(
o.name,
{ keyPath: o.keyPath, autoIncrement: o.autoIncrement }
);
app.indexedDB.addDataFromUrl( o.name, o.data_source );
});
}; // end request.onupgradeneeded()
// This method is called before the "onupgradeneeded" has finished..??
request.onsuccess = function( e ) {
app.indexedDB.db = e.target.result;
app.ui.updateStatusBar( 'Database initialized...' );
// ***
// Would like to query the database here but in Firefox the data has not
// always been added at this point... Works in Chrome.
//
}; // end request.onsuccess()
request.onerror = app.indexedDB.onerror;
}; // end app.indexedDB.open()
app.indexedDB.addDataFromUrl = function( store, url ) {
var xhr = new XMLHttpRequest();
xhr.open( 'GET', url, true );
xhr.onload = function( event ) {
if( xhr.status == 200 ) {
console.log('*** XHR successful');
// I would be adding the JSON data to the database object stores here.
}
else{
console.error("addDataFromUrl error:", xhr.responseText, xhr.status);
}
};
xhr.send();
}; // end app.indexedDB.addDataFromUrl()
})();
谢谢!
您可能遇到的问题之一是indexeddb中的自动提交功能。如果事务在短时间内处于非活动状态,它将提交事务并关闭它
在您的情况下,您正在调用一个异步方法来填充数据,这就是事务可能变为非活动的原因。如果在app.indexedDB.addDataFromUrl(o.name,o.data_source)之后添加console.write;您将看到它将在检索数据之前被调用,从而导致事务的提交。这就是调用成功回调时数据不存在的原因。chrome中的事务超时可能比Firefox中的要高。规范中没有对其进行描述,因此可能因供应商而异。
顺便说一句,如果您想在ajax调用中添加数据,您还必须将对象存储作为参数传递。
在if( xhr.status == 200 ) {}
中执行必须执行的操作从那里调用事务,将数据放入objectStore,然后您还需要
编辑:
我是这样做的,对我来说很有效,oncomplete函数只有在插入所有数据并准备好使用objectStore时才会被调用:
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://...", true);
xhr.addEventListener("load", function(){
if(xhr.status === 200){
console.info("Data received with success");
var data = JSON.parse(xhr.responseText);
var transaction = db.transaction([STORe],'readwrite');
var objstore = transaction.objectStore(STORE);
for(i = 0; i < data.length; i++){
objstore.put(data[i]);
};
transaction.oncomplete = function(event){
//do what you need here
console.info("Inserted data: " + data.length);
};
transaction.onerror = function(event){
};
transaction.onabort = function(event){
};
transaction.ontimeout = function(event){
};
transaction.onblocked = function(event){
};
};
}, false);
xhr.send();