为什么在连接到 indexedDB 时有时会在 onupgradeneeded 之前调用 onsuccess?

ndd*_*ery 5 html javascript asynchronous indexeddb

我在使用 IndexedDB 时遇到了问题。在 Firefox 18 上,当我创建一个新数据库时,onsuccess同时调用该方法具有onupgradeneeded. 在 Chrome 24 上(这是我想要的行为),该onsuccess方法仅在该onupgradeneeded方法完成后调用。

根据关于 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()
})();
Run Code Online (Sandbox Code Playgroud)

谢谢!

Kri*_*ave 5

您可能遇到的问题之一是 indexeddb 中的自动提交功能。如果事务在短时间内变为非活动状态,它将提交事务并关闭它。

在您的情况下,您正在调用异步方法来填充数据,这就是事务可能变得不活动的原因。如果在 app.indexedDB.addDataFromUrl( o.name, o.data_source ) 之后添加一个 console.write ;你会看到它会在你的数据被检索之前被调用,从而导致事务的提交。这就是调用成功回调时数据不存在的原因。chrome 中的事务超时时间可能比 Firefox 中的要高。它没有在规范中描述,因此它可能因供应商而异。

顺便说一句,如果您想在 ajax 调用中添加数据,您还必须将对象存储作为参数传递。