3

I have to return query result from indexedDB, but the result is only available in onsuccess event handler.

1  function listPeople(){
     ...
4    var open = indexedDB.open("AccordionDatabase",1),
5        res;
6
7    open.onsuccess = function(){
8        var db = open.result;
9        var transaction = db.transaction("PeopleStore", "readwrite");
10        var store = transaction.objectStore("PeopleStore");
11        var request = store.getAll();
12        request.onsuccess = function(event){
13            res = event.target.result;
14            console.log(res);
15        };
16
17        // Close the db when the transaction is done
18        transaction.oncomplete = function() {
19            db.close();
20        };
21
22    };
23    return res;
24 }

The output of the function call shows undefined, though console prints the result array. Please guide me how to use the variable as output.

Miron
  • 1,007
  • 2
  • 17
  • 31
  • You don't return from the handler, you handle the results in the `onsuccess` handler, or call an external function to handle results. – Teemu Sep 20 '17 at 15:34
  • If so, couldn't we use indexedDB query results in those cases? Is it only for function parameters? – Miron Sep 20 '17 at 15:46
  • I'm not sure if I understood your last comment. The request is asynchronous, returning from `listPeople` will happen before the results are defined. Please see http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call/14220323#14220323 – Teemu Sep 20 '17 at 15:53
  • I want to ask if there is no way to return results from indexedDB directly. – Miron Sep 20 '17 at 16:12
  • No, there's no way to do that. – Teemu Sep 20 '17 at 16:18
  • @Teemu, Thank you for your kind help. Then, indexedDB must have very limited usages, I guess. I need to migrate from indexedDB to other solution, such as localStorage. – Miron Sep 20 '17 at 16:23
  • It is not limited, it's just asynchronous, which needs a bit different logic to handle with. That is something worth of learning, you will bump into it in the future very often. – Teemu Sep 20 '17 at 16:25
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/154921/discussion-between-miron-and-teemu). – Miron Sep 20 '17 at 16:27
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Josh Oct 12 '19 at 18:19

2 Answers2

5

you can either use this project: https://github.com/jakearchibald/idb

or you need to wrap indexedDB operation into a promise and thus make the list people asynchronous:

function listPeople() {
// ...
  return new Promise(function (resolve, reject) {
    var open = indexedDB.open("AccordionDatabase",1),
    open.onsuccess = function() {
      var db = open.result;
      var transaction = db.transaction("PeopleStore", "readwrite");
      var store = transaction.objectStore("PeopleStore");
      var request = store.getAll();
      request.onsuccess = function(event){
        resolve(event.target.result);
      };

      request.onerror = function(event) { reject(event) }

      // Close the db when the transaction is done
      transaction.oncomplete = function() {
        db.close();
      };
      transaction.onerror = function(event) { reject(event) }
    };
    open.onerror = function(event) { reject(event) }
  })
}

// usage:
function doWorkWithListedPeople(people) {
  // ...
}

function handleErrorsDuringIndexedDbRequest(event) {
  // ...
}

listPeople().then(doWorkWithListedPeople).catch(handleErrorsDuringIndexedDbRequest)

// or also
listPeople().then(function(people) { doWorkWithListedPeople(people) })

The thing is, you create a promise that represents work that will be eventually done. You can tell JS that eventually, when the promise has been resolved (success), you want to then to work with anything that has been passed to resolve. See https://developer.mozilla.org/cs/docs/Web/JavaScript/Reference/Global_Objects/Promise and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function for details


EDIT

furthermore, if you don't like thens, you can make do with async await, which unwraps promises. Just beware, you can only use await keyword from within async function:

async function doStuff() {
  try {
    var people = await listPeople()
    // now you can work with ppl
  }
  catch (err) {
    // handle listPeople errors here
  }
}
netchkin
  • 1,387
  • 1
  • 12
  • 21
  • 1
    Thanks, This is what I am finding for. And thanks `Javascript` for providing `Promise`. – Miron Nov 25 '17 at 01:54
-3

indexedDB functions are nearly all asynchronous. You should be familiar with writing asynchronous Javascript before using indexedDB.

Josh
  • 17,834
  • 7
  • 50
  • 68
  • Don't you know either? This answer is too general. Actually, anyone can answer this way. – Miron Sep 20 '17 at 22:54
  • 1
    It is the most basic answer you are probably going to get without repeating answers already provided to the same question – Josh Sep 20 '17 at 23:44