Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Errors with IndexedDB versions and Dexie.js

I´m starting with IndexedDB and to not reinvent the wheel I´m using Dexie.js https://github.com/dfahlander/Dexie.js

I created the database, I added data and now I´m creating a generic function that get a CSV and populate the database in anothers tables.

So, more or less my code is

// Creation and populate database and first table
var db = new Dexie("database");
db.version(1).stores({table1: '++id, name'});

db.table1.add({name: 'hello'});

Until here all is OK

Now, in success of ajax request

db.close();
db.version(2).stores({table2: '++id, name'});
db.open();

db.table2.add({name: 'hello'});

First time this code run everything is OK, but next time I get this error

VersionError The operation failed because the stored database is a 
higher version than the version requested.

If I delete database and run code again only first time works OK.

Any idea? I don´t like too much IndexedDB version way, it´s looks frustrating and I don't get lot of help in the Net Thanks.

Edit: I discover the ¿problem/bug/procedure?. If I don´t add nothing before any version modification I haven't this issue, but does somebody know if is this the normal procedure?

So.. if this is the procedure I can't add any table dinamycally with a generic method. First all declarations and then add values. Any possibility to add a table after add values?

Edit again... I just realized that I could create another database. I'll post results. But any information about this issue is welcome :)

Edit again... I created dinamycally another database and everybody is happy!!

like image 659
john_smith_72 Avatar asked Aug 17 '16 15:08

john_smith_72


People also ask

Why use Dexie instead of IndexedDB?

Dexie solves three main issues with the native IndexedDB API: Dexie provides a neat database API with a well thought-through API design, robust error handling, extendability, change tracking awareness and extended KeyRange support (case insensitive search, set matches and OR operations). Yes, it’s that simple.

What are IndexedDB databases?

IndexedDB databases are unique to each web application. This means that an application can only access data from an IndexedDB database that runs on the same domain or subdomain as itself. The database is what houses the object stores, which in turn contain the stored data. To work with IndexedDB databases, we’ll need to open (or connect to) them:

Is Dexie backend asynchronous?

Dexie, as its backend indexedDB implementation, is an asynchronous database, meaning that any operation that requires a result won’t be returned directly. Instead all such operations will return a Promise. Dexie also supports queuing operations, meaning you can start using the database directly after having defined it.

How does Dexie initialize the last version of a store?

If no database present, Dexie initializes the last version directly by parsing the stores schema syntax and adding stores and indexes accordingly. No upgrade () functions run in this case. If a previous version is installed, Dexie will filter out the diff between each version and add/remove stores and indexes sequentially.


1 Answers

That is because the second time the code runs, your database is on version 2, but your main code still tries to open it at version 1.

If not knowing the current version installed, try opening dexie in dynamic mode. This is done by not specifying any version:

var db = new Dexie('database');
db.open().then(function (db) {
    console.log("Database is at version: " + db.verno);
    db.tables.forEach(function (table) {
        console.log("Found a table with name: " + table.name);
    }); 
});

And to dynamically add a new table:

function addTable (tableName, tableSchema) {
    var currentVersion = db.verno;
    db.close();
    var newSchema = {};
    newSchema[tableName] = tableSchema;

    // Now use statically opening to add table:
    var upgraderDB = new Dexie('database');
    upgraderDB.version(currentVersion + 1).stores(newSchema);
    return upgraderDB.open().then(function() {
        upgraderDB.close();
        return db.open(); // Open the dynamic Dexie again.
    });
}

The latter function returns a promise to wait until it's done before using the new table.

If your app resides in several browsers, the other windows will get their db connection closed as well so they can never trust the db instance to be open at any time. You might want to listen for db.on('versionchange') (https://github.com/dfahlander/Dexie.js/wiki/Dexie.on.versionchange) to override the default behavior for that:

db.on("versionchange", function() {
    db.close(); // Allow other page to upgrade schema.
    db.open() // Reopen the db again.
        .then(()=> {
           // New table can be accessed from now on.
        }).catch(err => {
           // Failed to open. Log or show!
        });
    return false; // Tell Dexie's default implementation not to run.
};
like image 189
David Fahlander Avatar answered Oct 31 '22 00:10

David Fahlander