0x_Anakin
0x_Anakin

Reputation: 3269

indexedDB can't insert data in database on "onupgradeneeded" event

The error I'm getting is:

Uncaught InvalidStateError: Failed to execute 'createObjectStore' on 'IDBDatabase': The database is not running a version change transaction.

And here is the code:

    var Database = function ( settings, catalogue ) {

        window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

        if ( !window.indexedDB ) {
            throw new Error("IndexedDB not supported!");
        }

        var that = this;
        this.settings = settings;
        this.catalogue = catalogue;
        this.db = null;

        var request = indexedDB.open( this.settings.name, this.settings.version );

        request.onerror = function ( e ) {
            //e.message = "Database initialization error";
            console.error( "Database initialization error:", e );
        };

        request.onsuccess = function ( e ) {

            console.log( "Database initialization success" );

            // that.db = e.target.result;
            // that.db.onerror = function ( e ) {
            //  console.error( "Database error:", e.target.errorCode );
            // };

        };

        request.onupgradeneeded = function ( e ) { 

            console.log( "Database upgrade required" );

            var db = e.target.result;
                db.onerror = function ( e ) {
                    console.error("Database upgrade error:", e.target.errorCode);
                };

            that.catalogue.retrieve( function ( catalogue ) {   

                console.log(catalogue)

                var stores = {};

                for ( var categoryKey in  catalogue ) {

                    var category = catalogue[categoryKey];

                    if ( category.length > 0 ) {

                        var schemaProduct = category[0];

                        stores[categoryKey] = db.createObjectStore(categoryKey, { keyPath: "id" });

                        for ( var prop in schemaProduct ) {

                            stores[categoryKey].createIndex( prop, prop, { unique: false } );

                        }

                        stores[categoryKey].transaction.oncomplete = function( e ) {

                            var transaction = db.transaction(categoryKey, "readwrite").objectStore(categoryKey);

                            for ( var productKey in category ) {
                                transaction.add( category[productKey] );
                            }


                            console.log("Insertion complete!") // this never fires
                        }


                    }

                }

            });


        };  



    }

var database = new Database( this.options.store.database, new Catalogue( this.options.store.catalogue ) );

I need a pair of fresh eyes because I can't seem to understand why this isn't working I rewrote the code a couple of times but apparrenlty I'm missing something.

PS: this.catalogue is an object with an ajax request which gets the data from the server. The data are correct.

Upvotes: 0

Views: 3497

Answers (1)

Josh
Josh

Reputation: 18690

Just a guess but usually this is because you are using two different asynchronous systems together. While it is possible in limited situations, you generally want to avoid calling non-indexedDB ajax functions like an async flagged XMLHttpRequest. A simple fix would be to call catalogue.retrieve first, and then call indexedDB.open with a higher version within catalogue.retrieve's callback. This way the statements within the onupgradeneeded transaction occur while the VERSION_CHANGE transaction is active. Right now it looks like the transaction becomes in active (the onupgradeneeded function finishes and exits) before the call to catalogue.retrieve completes.

In other words, do:

catalogue.retrieve(function(catalogue) {
  var r = indexedDB.open(...);
  r.onupgradeneeded = function() {
   var db = r.result;
   for(var k in catalogue) {
     //...
     db.createObjectStore(...);
   }
  };
});

Upvotes: 1

Related Questions