Skip to content

Dexie.waitFor()

David Fahlander edited this page Nov 25, 2016 · 27 revisions

Since Dexie 2.0.0-beta.5

Syntax

Dexie.waitFor(promise, timeout=60000)
Dexie.waitFor(promiseReturningFunction, timeout=60000)

Return Value

Promise

Description

This method makes it possible execute asynchronic non-indexedDB work while still keeping current transaction alive. To accomplish this, a separate "thread" will keep the transaction alive by propagating dummy-requests on the transaction while the given promise or async function is being executed. Use this method with caution as it may keep a transaction alive for a long time in case the given promise is late to resolve. Keeping transaction alive means that it will block operations from other transactions while being locked.

This method kind of violate a "holy principle" with IndexedDB. At the same time, it is in line with the new indexeddb-promises proposal where this will be possible. So in a future version if the proposal goes live, Dexie will start ride upon that new API if the browser supports it.

NOTE: indexeddb-promises currently has a slightly different method, waitUntil(), that works almost like this method, except that transaction is committed once the promise completes (as the proposal is today). The reason for naming it differently in Dexie is to distinguish it from the proposal's behavior.

Sample 1

function sleep (ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
await db.transaction('rw', db.friends, async ()=> {
    await Dexie.waitFor(sleep(100)); // Sleeps 100 milliseconds
    await db.friends.put({id: 1, name: "Åke"});
    await Dexie.waitFor(sleep(100)); // Sleeps 100 milliseconds
    let theMan = await db.friends.get(1);
    alert (`I still got the man: ${theMan.name}`);
});

The above sample shows that you can wait for non-IndexedDB Promises to complete while still keeping transaction alive. Note that while that promise is being executed, the transaction will be temporarily in an inactive state, so the operation must not work on your transaction - only non-transaction stuff.

Sample 2

await db.transaction('rw', db.friends, async (trans)=> {
    let theMan = await db.friends.get({name: "Åke"});
    // Keep our transaction alive while starting another one on a different database:
    await Dexie.waitFor(async ()=>{
        // In this scope, there's no currentTransaction going on.
        // We can start new transactions, work with non-indexedDB API's, or as in this sample,
        // do a separate operation (or transaction) onto another database, while the
        // above transaction is waiting for us:
        logDB.log.add({time: new Date(), event: "Fetched the man " + theMan.name});

        assert (Dexie.currentTransaction === null);
    });
    assert (Dexie.currentTransaction === trans);
});

The above sample shows how the method behaves when supplying a function to it. The function will be executed in a zone that does not derive the ongoing transaction. This is logical since the ongoing transaction may temporarily be in an inactive state while between the non-indexeddb promises that the function may await. The sample shows that it is possible to keep the main transaction alive also while doing things on other separate transaction, maybe on other databases or API:s.

Clone this wiki locally