Freelex
Freelex

Reputation: 186

Wait for openCursor to finish in IndexedDB

I have this code:

html5DB.indexedDB.addSomething = function(foo) {
    var db = html5DB.indexedDB.db;
    var trans = db.transaction(["something"], "readwrite");
    var store = trans.objectStore("something");

    var isExisting = IsAlreadyExist(foo);
    // How to wait for that instruction to finish?

    if (!isExisting){
       var request = store.put({
           "text": foo,
           "timeStamp" : new Date().getTime()
       });
    }
};

I'm trying to understand how can I wait for the function IsAlreadyExist to finish. This function opens a cursor to iterate in the object store to determinate if a particular value exist.

Actually, there is no error, but I can't reach the code inside the if (!isExisting) because the value of the variable never changes.

This is the code of that second function:

function IsAlreadyExist(foo){
    var db = html5DB.indexedDB.db;
    var objectStore = db.transaction("something").objectStore("something");

    objectStore.openCursor().onsuccess = function(event) {
        var cursor = event.target.result;

        if (cursor) {
            if (cursor.value.text == foo)   
                return true;

            cursor.continue();
       }
    };

    return false;
}

Is there a way to wait for the end of the execution? Or maybe it is not a good way to proceed for checking if a value exist?

Upvotes: 2

Views: 3698

Answers (1)

Aaron Powell
Aaron Powell

Reputation: 25099

As IndexedDB is an asynchronous API you have to wait until operations are completed using callbacks.

First off we need to refactor the IsAlreadyExist method:

function IsAlreadyExist(foo, oncomplete) {
    var db = html5DB.indexedDB.db;
    var transaction = db.transaction("something");
    var objectStore = transaction.objectStore("something");

    var exists = false;

    objectStore.openCursor().onsuccess = function(event) {
        var cursor = event.target.result;

        if (cursor) {
            if (cursor.value.text == foo) {
                exists = true;
                return;
            }

            cursor.continue();
       }
    };

    transaction.oncomplete = function () {
        oncompleted(exists);
    };
}

Now we'll refactor your other method:

html5DB.indexedDB.addSomething = function(foo) {
    IsAlreadyExist(foo, function (isExisting) {
        if (!isExisting){
           var db = html5DB.indexedDB.db;
           var trans = db.transaction(["something"], "readwrite");
           var store = trans.objectStore("something");

           var request = store.put({
               "text": foo,
               "timeStamp" : new Date().getTime()
           });
        }
    });
};

So here you'll see we're passing the function to execute when the cursor search is done as a callback, which receives an argument of the status.

This can start getting a bit ugly, which is why Promise's are popular in JavaScript. I wrote a wrapper for IndexedDB that uses a Promise-based API called db.js.

Upvotes: 5

Related Questions