Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indexeddb: return value after openrequest.onsuccess

Tags:

indexeddb

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'

like image 494
haipham23 Avatar asked Apr 28 '26 16:04

haipham23


2 Answers

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"
});
like image 168
Mark Vayngrib Avatar answered May 01 '26 12:05

Mark Vayngrib


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){...});
like image 31
Matt Guillot Avatar answered May 01 '26 11:05

Matt Guillot