5

IndexedDB に問題があります。Firefox 18 では、新しいデータベースを作成すると、onsuccessメソッドが呼び出されると同時に has 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()
})();

ありがとう!

4

2 に答える 2

5

おそらくあなたが苦しんでいることの 1 つは、indexeddb の自動コミット機能です。トランザクションが短時間非アクティブになった場合、トランザクションはコミットされ、クローズされます。

あなたの場合、非同期メソッドを呼び出してデータを埋めているため、トランザクションが非アクティブになる可能性があります。app.indexedDB.addDataFromUrl( o.name, o.data_source ); の後に console.write を追加した場合 データが取得される前に呼び出され、トランザクションがコミットされることがわかります。これが、成功のコールバックが呼び出されたときにデータが存在しない理由です。Firefox よりも Chrome の方がトランザクションのタイムアウトが長くなる可能性があります。仕様には記載されていないため、ベンダーによって異なる場合があります。

ところで、ajax 呼び出しにデータを追加する場合は、オブジェクト ストアもパラメーターとして渡す必要があります。

于 2013-02-16T06:45:41.620 に答える
1

if( xhr.status == 200 ) {} そこからトランザクションを呼び出し、データをobjectStoreに入れ、さらに必要なものを内部で行う必要があります

編集:

すべてのデータが挿入され、objectStore が使用可能になると、oncomplete 関数が呼び出されます。

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();
于 2013-02-16T20:35:15.330 に答える