Dexie.js: Running nested queries fails?

Created on 29 Apr 2017  路  6Comments  路  Source: dfahlander/Dexie.js

Take the following code,

db_class.user.get(function (user) { 
    if (!user.is_drag_and_drop_enabled) {
        db_class.user.update({
            is_drag_and_drop_enabled: 0
        }, function (updated) {});
    }
});

when it executes I get this error in the console,

dexie.js:1 Unhandled rejection: ReadOnlyError: Transaction is readonly

why is this?

It gets the data fine, I #tested it by doing a console.log and it was showing the right data. The update function is this,

update: function (changes, callback) {
    return db.user.update(1, changes).then(function (updated) {
        return is_function(callback) ? callback(updated) : false;
    });
}

when I run the function outside of the get function, it works fine.

All 6 comments

I assume you have your code surrounded by a transaction scope (inline or in a caller of your function) :

db.transaction('r',... () => {
    //your code here
}) ;

If so, just change 'r' to 'rw' in that transaction.

Sometimes, you cannot control the fact that the caller does specify transaction. If that is the case, you'll need to specify your transaction, and look into the '!' or '?' transaction modes documented here: http://dexie.org/docs/Dexie/Dexie.transaction()

@dfahlander Out of curiosity, why is it like that?

It's becuase the indexedDB transaction was opened in a readonly state. For a full explanation of how transaction scopes work, read throw this doc page. I hope it explains the details: http://dexie.org/docs/Dexie/Dexie.transaction()

There is one thing that may trip people who are unaware of the details of how Dexie works. If they start a query that reads a table and during this query, start another query that modifies the database, they may run into ReadOnlyError: Transaction is readonly.

I ran into the issue with code that did a table.where(...).each(...) and the callback to .each() was changing the database. My immediate thought was "hmm.... I'm not using transactions" because I never call db.transaction explicitly, but the outer query does start a readonly transaction implicitly. And the code in .each() executes within that implicit transaction.

That's true. The issue is there's no way in indexedDB to upgrade a transaction to be readwrite. So there would be two options of solving this. Either do the things within each as separate transactions (which could lead to performance issues), or better, provide a more explaining error message when each() is used transactionless. (Suggest using Collection.modify() instead, or use a 'rw' transaction scope around Collection.each())

There is one thing that may trip people who are unaware of the details of how Dexie works. If they start a query that reads a table and during this query, start another query that modifies the database, they may run into ReadOnlyError: Transaction is readonly.

I ran into the issue with code that did a table.where(...).each(...) and the callback to .each() was changing the database. My immediate thought was "hmm.... I'm not using transactions" because I never call db.transaction _explicitly_, but the outer query does start a readonly transaction _implicitly_. And the code in .each() executes within that implicit transaction.

If you run into this issue but there's no easy way round, because you need to some actions WITHIN the .each loop - I can recommend wrapping your actions into a timeout.

Was this page helpful?
0 / 5 - 0 ratings