Question

I have this function:

this.get = function() {
    var something = 0;
    window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
    window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
    window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
    if (!window.indexedDB) {
        return;
    }
    var openRequest = window.indexedDB.open("abc", 1);
    openRequest.onupgradeneeded = function (e) {
        var thisDB = e.target.result;
        if (!thisDB.objectStoreNames.contains("xyz")) {
            thisDB.createObjectStore("xyz");
        }
    }
    openRequest.onsuccess = function (e) {
        var transaction = e.target.result.transaction(["xyz"], "readwrite");
        var store = transaction.objectStore("xyz");

        var request = store.openCursor(1);
        request.onerror = function (e) {
        }
        request.onsuccess = function (e) {
            something = e.target.result.value.size;
            console.log(1);
        }
    }
    openRequest.onerror = function (e) {
    }
    console.log(2);
    return something;
};

As you can see, I expect that 'something' will be assigned with 'e.target.result.value.size' first, then will be returned.

However, indexeddb is asynchronous, so it will return 0 instead of 'e.target.result.value.size' (which means that the log will print out 2 first, then 1)

So my question is, how can I return value of 'e.target.result.value.size'

Was it helpful?

Solution

As you said, indexeddb is asynchronous, which means the "get" function CANNOT synchronously return e.target.result.value.size.

Usually what you do in this case is either provide a callback to "get", a la:

this.get = function(callback) {
   ...asynchronous operations...
   callback(e.target.result.value.size);
}

Or return a promise from "get":

this.get = function() {
   return $.Deferred(function(dfd) {
     ...asynchronous operations...
     dfd.resolve(e.target.result.value.size);
   }).promise();
}

This uses jQuery's Deferreds (jQuery's implementation of promises), but you can use any other implementation, such as Q, when, mpromise, and others. If you end up using promises, you would use "get" like this:

this.get().done(function(something) {
  // use "something"
});

OTHER TIPS

If someone is still trying to figure out with vanilla js you would do something like:

async function xx(){
    return new Promise(function(resolve, reject){
        let request = ...;
        request.onsuccess = function(){
            resolve(request.result);
        }
    });
}

xx().then(function(result){...});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top