Store retrieved data from indexed DB to a variable - javascript

I am using the following code to read data from Indexed DB and save it in variable allDownloadContent
ereaderdownload.indexedDB.getAllTodoItems = function() {
/*var todos = document.getElementById("todoItems");
todos.innerHTML = "";
*/
var db = ereaderdownload.indexedDB.db;
var trans = db.transaction(["downloadcontent"], "readwrite");
var store = trans.objectStore("downloadcontent");
var request = store.get(0);
request.onsuccess = function(e) {
console.log(e.target.result);
};
// Get everything in the store;
var cursorRequest = store.openCursor();
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(!!result == false)
return;
allDownloadContent.push(result);
result.continue();
};
alert("content "+allDownloadContent[0]);
cursorRequest.onerror = ereaderdownload.indexedDB.onerror;
};
When I call the getAllTodoItems method from another Javascript file I am getting a alert message content undefined
since the cursorRequest.onsuccess method executes async I am getting undefined.
I cannot make use of web workers since it is not supported in chrome.
I tried promise in Jquery. Still I am getting the same alert message.
Please help me in resolving the issue.

As for now all browsers only support the Indexed-db ASync API, and what you need to do is add an event listener to the transaction oncomplete event. This event will fire when cursor is closed. From there you can return to your code:
trans.oncomplete = function (event) {
console.log('transaction completed');
yourFunction();
};

Related

How To Add Index to Pre-Existing ObjectStore In IndexedDB

I know this questions has been asked several times . But I have not been able to find out the solution after getting error multiple times . this is the code of my indexed db
request.onupgradeneeded = function(event) {
var db = event.target.result;
var upgradeTransaction = event.target.transaction;
var objectStore = db.createObjectStore("todostore", {keyPath: "timestamp"});
UserFunction();
};
function UserFunction(){
var ObjectStore = db.transaction("todostore").objectStore("todostore");
var index = ObjectStore.createIndex("ixName", "fieldName");
}
Failed to execute 'createIndex' on 'IDBObjectStore': The database is not running a version change transaction.
I am calling this function of button click I want to add index with value when a button is clicked
<button onclick="UserFunction()">createIndex</button>
You can only change the schema of the database during a version upgrade. Something like this is plausible:
function OnClick() {
// assumes db is a previously opened connection
var oldVersion = db.version;
db.close();
// force an upgrade to a higher version
var open = indexedDB.open(db.name, oldVersion + 1);
open.onupgradeneeded = function() {
var tx = open.transaction;
// grab a reference to the existing object store
var objectStore = tx.objectStore('todostore');
// create the index
var index = objectStore.createIndex('ixName', 'fieldName');
};
open.onsuccess = function() {
// store the new connection for future use
db = open.result;
};
}
Code in UserFunction() call, is starting a new transaction, while already a transaction is going on in "upgradeneeded" listener.
So new transaction should be started, after objectStore.transaction completes.
Here is the JSFiddle : Solution is here
function UserFunction(){
var request = window.indexedDB.open("MyTestDatabase", 3);
request.onupgradeneeded = function(event) {
var db = event.target.result;
var upgradeTransaction = event.target.transaction;
var objectStore = db.createObjectStore("todostore", {keyPath: "timestamp"});
objectStore.transaction.oncomplete = function(event) {
addIndex(db);
};
};
}
function addIndex(db){
var ObjectStore = db.transaction("todostore").objectStore("todostore");
var index = ObjectStore.createIndex("ixName", "fieldName");
}

IndexedDB open DB request weird behavior

I have an app (questionnaire) that uses indexedDB.
We have one database and several stores in it.
Stores have data already stored in them.
At some point a dashboard html file is loaded. In this file I am calling couple of functions:
function init(){
adjustUsedScreenHeight();
db_init();
setInstitutionInstRow();
loadRecommendations();
loadResultsFromDB();
fillEvaluations();
document.addEventListener("deviceready", onDeviceReady, function(e) {console.log(e);});
}
The init() function is called on body onLoad.
setInstitutionInstRow() looks like these:
function setInstitutionInstRow(localId){
//localId = 10;
if (localId == undefined){
console.log("Localid underfined: ");
//open db, open objectstore;
var request = indexedDB.open("kcapp_db", "1.0");
request.onsuccess = function() {
var db = request.result;
var tx = db.transaction ("LOCALINSTITUTIONS", "readonly");
var store = tx.objectStore("LOCALINSTITUTIONS");
tx.oncomplete = function(){
db.close();
}
tx.onerror = function(){
console.log("Transaction error on setInstInstRow");
}
var cursor = store.openCursor();
cursor.onsuccess= function () {
var match = cursor.result;
console.log ("Retrieved item: " + match.value.instid);
// alert("Added new data");
if (match){
setInstituionInstRow(match.value.instid);
console.log("Got localid: " + math.value.instid);
}
else
console.log("localinsid: it is empty " );
};
cursor.onerror = function () {
console.log("Error: " + item.result.errorCode);
}
}
request.onerror = function () {
console.log("Error: " + request.result.errorCode );
}
request.oncomplete = function (){
console.log("The transaction is done: setInstitutionRow()");
}
request.onupgradeneeded = function (){
console.log("Upgrade needed ...");
}
request.onblocked = function(){
console.log("DB is Blocked ...");
}
} else {
instid = localId;
var now = new Date();
//console.log("["+now.getTime()+"]setInstituionInstRow - instid set to "+localId);
//open db, open objectstore;
var request = indexedDB.open("kcapp_db", "1.0");
request.onsuccess = function() {
var db = this.result;
var tx = db.transaction ("INSTITUTIONS", "readonly");
var store = tx.objectStore("INSTITUTIONS");
var item = store.get(localId);
console.log(item);
item.onsuccess= function () {
console.log ("Retrieved item: ");
if (item.length > 0)
var lInstitution = item.result.value;
kitaDisplayValue = lInstitution.krippe;
};
item.onerror = function () {
console.log("Error: " + item.result.errorCode);
}
}
request.onerror = function () {
console.log("Error: " + request.result.errorCode );
}
}
Now the problem is,
var request = indexedDB.open("kcapp_db", "1.0");
the above request is never getting into any onsuccess, oncomplete, onerror states. I debugged with Chrome tools, it never getting into any above states.
Accordingly I am not getting any data from transactions.
And there are no errors in Chrome console.
And here is the request value from Chrome dev:
From above image the readyState: done , which means it should fire an event (success, error, blocked etc). But it is not going into any of them.
I am looking into it, and still can not figure out why it is not working.
Have to mention that the other functions from init() is behaving the same way.
Looking forward to get some help.
You may be using an invalid version parameter to the open function. Try indexedDB.open('kcapp_db', 1); instead.
Like Josh said, your version parameter should be an integer, not a string.
Your request object can get 4 events in response to the open request: success, error, upgradeneeded, or blocked. Add event listeners for all of those (e.g. request.onblocked = ...) and see which one is getting fired.
I had that problem but only with the "onupgradeneeded" event. I fixed it changing the name of the "open" function. At the begining I had a very long name; I changed it for a short one and start working. I don't know if this is the real problem but it was solved at that moment.
My code:
if (this.isSupported) {
this.openRequest = indexedDB.open("OrdenesMant", 1);
/**
* Creación de la base de datos con tablas y claves primarias
*/
this.openRequest.onupgradeneeded = function(oEvent) {
...
Hope it works for you as well.

indexedDB openCursor transaction onsuccess returns empty array

req = db.openCursor();
req.customerData=new Array() //[{a:1}]
req.onsuccess = function(e) {
var cursor = e.currentTarget.result;
if (cursor) {
//console.log(cursor.value);
e.currentTarget.customerData.push(cursor.value);
e.currentTarget.customerData.push("hello?");
cursor.continue()
}
else {
console.log(e.currentTarget.customerData) //this always correct
}
}
console.log(req.customerData); //outside the onsuccess everything is gone?
console.log(req);
I can see customerData when I open the object in the chrome console
console.log(req.customerData);
But when I do the above it is empty?
replacing new Array() with [{a:1}]
console.log(req.customerData);
I can see a and also the other objects
but then agian
console.log(req.customerData[0].a);
works and the other objects are gone.
How can I save customerData? I tried just pushing numbers or text but same thing after transaction is done. I can't get the data out only display it on console.log() during the transaction?
I know it must be something past by reference but every variable I trow in dissapears?
Added full example below just type write() and read() in console
<script>
var iDB
ready=function(){
var request = indexedDB.open("my-database",1);
request.onupgradeneeded = function(e) {
var db = e.currentTarget.result
var store = db.createObjectStore("store", {keyPath: "muts", autoIncrement:false})
//store.createIndex("by_submit", "submit", {unique: false})
console.log('db upgrade', 'v'+db.version)
}
request.onerror = function(e) {
//var db = e.currentTarget.result;
//db.close()
console.error('db error ',e)
}
request.onsuccess = function(e) {
var db = e.currentTarget.result
db.onversionchange = function(e) {
db.close()
console.log('db changed', 'v'+db.version, 'CLOSED')
}
console.log('db setup', 'v'+db.version, 'OK')
}
iDB=request
}
drop=function(){
iDB.result.close()
var req = indexedDB.deleteDatabase(this.iDB.result.name);
req.onsuccess = function() {console.log("Deleted database successfully")}
req.onerror = function() {console.log("Couldn't delete database")}
req.onblocked = function() {console.log("Couldn't delete database due to the operation being blocked")}
}
read=function(){
var db=iDB
.result
.transaction(["store"], "readwrite").objectStore("store");
var req = db.openCursor();
req.iData=new Array();
req.onsuccess = function(e) {
var cursor = e.currentTarget.result;
if (cursor) {
e.currentTarget.iData.push(cursor.value);
e.currentTarget.iData.push("hello");
cursor.continue()
}
else {
console.log(e.currentTarget.iData)
}
}
console.log(req.iData)
}
write=function(){
var db=document.querySelector('my\-database')
.iDB
.result
.transaction(["store"], "readwrite").objectStore("store");
var customerData = [
{muts: "Bill", qty: "1"},
{muts: "Donna", qty: "1"}
]
for (var i in customerData){db.put(customerData[i])}
}
ready()
</script>
A few things
I recommend not setting custom properties of an IDBRequest object. Create and access objects that are in an outer scope instead.
There is no need to use event.currentTarget. event.target is sufficient (and so is 'this', and so is the request object itself).
onversionchange is deprecated.
Due to the asynchronous nature of indexedDB, you may be trying to print something out to the console that does not yet exist, or no longer exists. Instead, try printing something out when the transaction completes.
For example:
function populateArray(openDatabaseHandle, onCompleteCallbackFunction) {
var transaction = openDatabaseHandle.transaction('store');
var store = transaction.objectStore('store');
var myArray = [];
var request = store.openCursor();
request.onsuccess = function() {
var cursor = this.result;
if(!cursor) return;
myArray.push(cursor.value);
cursor.continue();
};
transaction.oncomplete = function() {
onCompleteCallbackFunction(myArray);
};
}
// An example of calling the above function
var conn = indexedDB.open(...);
conn.onsuccess = function() {
populateArray(this.result, onPopulated);
};
// An example of a callback function that can be passed to
// the populateArray function above
function onPopulated(data) {
console.debug(data);
data.forEach(function(obj) {
console.debug('Object: %o', obj);
});
}

Why is db.transaction not working with indexeddb?

I am new at using inxededdb and am trying to get data out of a store. The store contains data, but for some reason the code stops after trying to set the var tx. If I am missing anything please let me know. Here is the function with which I am trying to get the book:
function getBook(){
var tx = db.transaction("book", "readonly");
var store = tx.objectStore("book");
var index = store.index("by_getid");
var request = index.get("<?php echo $_GET['book'] ?>");
request.onsuccess = function() {
var matching = request.result;
if (matching !== undefined) {
document.getElementById("text-container").innerHTML = matching.text;
} else {
alert('no match');
report(null);
}
};
}
Solved Version:
function getBook(){
var db;
var request = indexedDB.open("library", 1);
request.onsuccess = function (evt) {
db = request.result;
var transaction = db.transaction(["book"]);
var objectStore = transaction.objectStore("book");
var requesttrans = objectStore.get(<?php echo $_GET['book'] ?>);
requesttrans.onerror = function(event) {
};
requesttrans.onsuccess = function(event) {
alert(requesttrans.result.text);
};
};
}
The problem is probably your db variable. You are probably accessing a closed or null instance of a connection object.
Try instead to create the db connection right inside the function. Do NOT use a global db variable.
index.get yields primary key. You have to get record value using the resulting primary key.
I has problem with transaction, it's return error db.transaction is not a function or return undefined.
You will try like this, it's working for me:
const table = transaction.objectStore('list');
const query = table.getAll();
query.onsuccess = () => {
const list = query?.result;
console.log(list);
};

Error "A mutation operation was attempted on a database that did not allow mutations." when retrieving data in indexedDB

I have this simple example code:
var request = mozIndexedDB.open('MyTestDatabase');
request.onsuccess = function(event){
var db = event.target.result;
var request = db.setVersion('1.0');
request.onsuccess = function(event){
console.log("Success version.");
if(!db.objectStoreNames.contains('customers')){
console.log("Creating objectStore");
db.createObjectStore('customers', {keyPath: 'ssn'});
}
var transaction = db.transaction([], IDBTransaction.READ_WRITE, 2000);
transaction.oncomplete = function(){
console.log("Success transaction");
var objectStore = transaction.objectStore('customers');
};
};
};
I am getting this:
A mutation operation was attempted on a database that did not allow mutations." code: "6
on line
var objectStore = transaction.objectStore('customers');
Can't figure out - what do I do wrong?
You can create or delete an object store only in a versionchange transaction
see: https://developer.mozilla.org/en-US/docs/IndexedDB/IDBDatabase
I think I found the answer. I shouldn't access objectStore inside oncomplete. I just need to do it after making new transaction. Right way is this:
var transaction = db.transaction([], IDBTransaction.READ_WRITE, 2000);
transaction.oncomplete = function(){
console.log("Success transaction");
};
var objectStore = transaction.objectStore('customers');
Btw, this is how exactly Mozilla's MDN shows. https://developer.mozilla.org/en/IndexedDB/Using_IndexedDB#section_10
I didn't try that code but judging by the documentation you shouldn't pass an empty list as first parameter to db.transaction() - it should rather be db.transaction(["customers"], ...) because you want to work with that object store.

Categories

Resources