db.transaction ('rw',db.friends,async () => {for (let i=0; i<100; ++i) {// If you need to await something that may be non-promise,// Use Promise.resolve() around it.awaitPromise.resolve(null); }});
Dont call setTimeout() or any other async API from inside a transaction.
NOT OK:
let Promise =require('bluebird');db.transaction('r',db.friends, () => {// Promise is not the global Promise. It might break transactions.returnnewPromise((resolve, reject) => {db.friends.get(1).then(resolve, reject); });});
Don't use 3-rd party promises within transactions. Must only use Dexie.Promise or the built-in promise (window.Promise / self.Promise / global.Promise) within transactions.
THIS IS OK (in Dexie 2.0.0 and above):
db.transaction('r',db.friends,function () {// In Dexie 2.0, it's ok to use the global Promise (window.Promise)returnPromise.all([db.friends.get(1),db.friends.get(2) ]);});
THIS IS ALSO OK:
db.transaction('r',db.friends,async () => {// In Dexie 2.0, it's ok to use the global Promise (window.Promise)returnawaitPromise.all([db.friends.get(1),db.friends.get(2),Promise.resolve(3) // Encapsulate non-promises with Promise.resolve() when awaiting things. ]);});
Since Dexie 2.0, you may use the global Promise within transactions, since it will always be temporary patched within the transaction zone. But interactions with non-Dexie API:s must only be done outside transactions. For example if you need to fetch data from a REST API, do that before entering the transaction. And if you need to call REST API based on a database query, do that when your transaction completes.
THIS IS OK:
asyncfunctionsample() {// First, you fetch:let restData =awaitfetch(someUrl);// Then, you do the transaction:let dbResult =awaitdb.transaction('rw',db.someTable,async ()=> {let changedItems =awaitdb.someTable.where('changeDate').above(lastSyncDate).toArray();awaitdb.someTable.bulkPut(restData);return changedItems; });// When transaction has finally completed, you can interact with fetch again:awaitfetch(someUrl, {method:'POST', body: dbResult});}
In this trivial sync-sample, the fetch() API is only called from outside the transaction. The sample applies also to XMLHttpRequest, jQuery Ajax and any other asynchronic API except the Dexie API.
Dexie.waitFor()
You can also keep a transaction alive using Dexie.waitFor() within a transaction, but I would only recommend it when using definitive short-lived operations, such as the crypto API - and avoid using it on ajax calls as they may take long time to complete - and your transaction would be locked for a long time if so.
Parallel transactions
It's also OK to run several different database transactions in parallel. Transactions are maintained using zones.
The two transactions can run in parallel. Zones will make sure that each time someone uses a table, it will be invoked using that current transaction of that particular flow of async calls.