Dexie.js
Dexie.js copied to clipboard
Why does deleting not take into effect with cached liveQuery()?
After upgrading to the latest Dexie of v4.0.1-alpha.25
, the deleting operations does not take into effect, while all other kinds of operations (e.g. creating, retrieving & updating) work fine.
Our codes are like below:
function deleteByPageIds (pageIds: string[]) {
return db.transaction('rw', db.pages, db.sessions, () => Promise.all([
db.sessions.where('pageId').anyOf(pageIds).delete(),
db.pages.bulkDelete(pageIds),
]));
}
We debug into this function to make sure it is invoked with correct pageIds
. There are NO any errors thrown. However after the transaction finished, the corresponding records, that relate to the specified pageIds
in both pages
& sessions
, still exists.
It is also noticed that Devtools indicated the tables were modified. But even after reloaded the tables, the records are still there.
We have no ideas on why it happens and howto avoid. Could you please give us any suggestions or advices on this problem?
One assumption by now is due to the interoperation between standard Promise
and Dexie.Promise
. According to https://dexie.org/docs/Promise/Promise#interopability, and quoted as below
Another reason is that only Dexie.Promise has the capability to keep track of the currently executing transaction between calls (See Promise.PSD).
window.Promise is always safe to use within transactions, as Dexie will patch the global Promise within the transaction zone, but leave it untouched outside the zone.
A more detailed version about our codes is like:
// a facility function to fulfill deleting with a specified callback of `deleter`
function deleteWith (tables: Table[], deleter: () => Promisable<void>) {
// a transaction is launched with an expectation of possibly cascading
// with an outer transaction
return db.transaction('rw', tables, deleter);
}
class Session {
deleteByPageIds (pageIds: string[]) {
// delete records
return deleteWith([db.sessions], () =>
db.sessions.where('pageId').anyOf(pageIds).delete());
}
}
// a singleton instance of `Session`
const sessionDb = new Session();
class Page {
deleteIds (pageIds: string[]) {
// deleting recursively with a callback to delete internal/descendant objects
return deleteWith([db.pages, db.sessions], () => Promise.all([
// **PROBLEM: after executing the line below, the call stack lost the track to `Page.deleteIds()`**
sessionDb.deleteByPageIds(pageIds),
db.pages.bulkDelete(pageIds),
]));
}
}
The key problem, as noted within Page.deleteIds()
and above the line sessionDb.deleteByPageIds(pageIds)
, is that the call stack lost the track to previous asynchronous invocation. The problem does exist, though the accurate code might be different with the code snippet provided.
So, how could we fix this, e.g. how about sourrounding the returned promise with Dexie.Promise
like below
function deleteWith (tables: Table[], deleter: () => Promisable<void>) {
// a transaction is launched with an expectation of possibly cascading
// with an outer transaction
return Dexie.Promise.resolve(db.transaction('rw', tables, deleter));
}
It seems the problem occurs when invoking some APIs of the standard Promise
, according to https://dexie.org/docs/Tutorial/Best-Practices#not-ok. The code is like below
// NOT OK, since `.then()` is invoked within the transaction
db.transaction('rw', db.pages, db.sessions, () => Promise.all([
db.sessions.where('pageId').anyOf(pageIds).delete(),
db.pages.bulkDelete(pageIds),
]).then());
// OK, after `.then()` move outside of the transaction
db.transaction('rw', db.pages, db.sessions, () => Promise.all([
db.sessions.where('pageId').anyOf(pageIds).delete(),
db.pages.bulkDelete(pageIds),
])).then();
So, is this assumption and solution correct? Please give us some suggestions if possible.
Thanks!
There shouldn't be any issues of this kind what I know of. If you'd have a chance to create a stand-alone reproduction of the issue, I'd be happy to debug it and I'm sure we'll get to the bottom of the problem.
ran into this as well. removing Promise.all
fixed the problem.
will try to find time this weekend to spin up a test repo