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'

Était-ce utile?

La 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"
});

Autres conseils

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){...});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top