Why does indexedDB skip some data when adding to database? - javascript

I am using javascript to do this.
I want to add data to the database (indexedDB). The data will be coming from the webservice as json and I am looping through it and adding it to an objectStore with a keyPath.
When I look at the data from the webservice, I have an array of 186 objects but when I read the data from indexedDB, I have 151. When I went to check the database to see if the data was there, it wasn't... So something must be going on with my add function.
Here is my code:
Opening a database with an objectStore:
let db;
let request = window.indexedDB.open("WHS", 4);
request.onerror = function(event) {
console.log(event.target.errorCode);
};
request.onsuccess = function(event) {
db = event.target.result;
};
request.onupgradeneeded = function(event) {
let db = event.target.result;
let palletStore = db.createObjectStore("pallets", { keyPath: "palletno" });
};
Adding data after passing it to my function:
function addPalletsToIDB(pallets) {
let transaction = db.transaction(["pallets"], "readwrite");
let objectStore = transaction.objectStore("pallets");
$.each(pallets, function(i, pallet) {
let request = objectStore.put(pallet);
})
request.onsuccess = function(event) {
console.log('Added pallets : ', event.target.response);
};
transaction.oncomplete = function() {
getPalletDataFromIDB();
}
};
Reading the data:
function getPalletDataFromIDB() {
palletsFromIDB = [];
let transaction = db.transaction(["pallets"], IDBTransaction.READ);
transaction.oncomplete = function(event) {
console.log(event);
};
transaction.onerror = function(event) {
console.log(event.type);
};
let objectStore = transaction.objectStore("pallets");
objectStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
palletsFromIDB.push(cursor.value);
cursor.continue();
}
transaction.oncomplete = function() {
console.log("[palletsFromIDB] ", palletsFromIDB);
toastr.info("Got pallets");
};
};
};
from web service : {pallets: Array(186)}
from indexedDB : [palletsFromIDB] (151)

One way to do this is to just create a unique keyPath in your json and making that your keyPath in indexed db.

Related

IndexedDB: executing function with method add several times - no new DB-entry

I have created a function to store data in indexed db:
var request = window.indexedDB.open("mynewDB", 1);
request.onupgradeneeded = function(event) {
var db = event.target.result;
var objectStore = db.createObjectStore("toDoList", {keyPath: 'key', autoIncrement: true});
var txn = event.target.transaction;
var addRequest = txn.objectStore("toDoList").add({value: storagedata});
}
(FYI: the storagedata is filled with a base64 string)
If i am executing this function via button the content of variable storagedata is in the IndexedDB. But if i want to press the button again to store another value into the IndexedDB, nothing happens.
In addition to that if i am executing the function the second time the function jumps at line request.onupgradeneeded = function(event) { in to the timeout of file "intervalTrigger-dbg.js" to code clearTimeout(this._delayedCallId);
What i did to solve the problem: debugging in browser and reading a lot of documentations about indexeddb.
I fixed the problem on my own.
For everyone who want to know how it works:
var request = window.indexedDB.open("yourDB-1", 1);
var db;
var transaction;
var store;
request.onupgradeneeded = function(event) {
var db = event.target.result;
var transaction = event.target.transaction;
var store = db.createObjectStore("yourDB", {keyPath: 'key', autoIncrement: true});
}
request.onerror = function (event) {
console.log("Here is a error: " + event.target.errorCode);
}
request.onsuccess = function (event) {
db = request.result;
transaction = db.transaction("yourDB", "readwrite");
store = transaction.objectStore("yourDB");
db.onerror = function(event){
console.log("ERROR" + event.target.errorCode);
}
store.put({value: storagedata});
transaction.complete = function() {
db.close();
}
}

How to update object in IndexedDB from service worker

I'm trying to update an Object Store in IndexedDB from a Service Worker, this is my code right now:
function updateUrlLink(url_link) {
var request = indexedDB.open('db', 1);
var url_link_value = url_link;
request.onsuccess = function (event) {
var store = request.result.transaction("url_link", "readwrite").objectStore("url_link");
store.add(url_link_value, "url_link");
};
request.onupgradeneeded = function (event) {
var db = event.target.result;
var store = db.createObjectStore('url_link');
};
}
Is this the right way to update url_link or is there other way?

Javascript call method in another method

Now I'm trying to implement Unity Webgl with jslib. I'm so confused about how to call method in another method's function. I want to call method Recv when message was coming (ws.onmessage). But, it show "TypeError: this.Recv is undefined". Could you please help me figure out this source? Thank you !!!!!
Here's my source code
var ws = null;
var init_url = "";
var received_msg = "";
var error_msg = "";
var WebsocketLib = {
Hello: function(){
window.alert("Hello,world!");
},
InitSocket: function(url){
init_url = Pointer_stringify(url);
console.log("InitWebSocket: "+init_url);
ws = new WebSocket(init_url);
ws.onopen = function(evt){
console.log("Connect");
isConnected = false;
ws.send("hello");
};
ws.onclose = function(evt) {
console.log("Close");
isConnected = false;
};
ws.onmessage = function(evt) {
received_msg = evt.data;
console.log("[recv] "+received_msg);
this.Recv.call(this);
};
ws.onerror = function(evt) {
error_msg = evt.data;
console.log("[error] "+error_msg);
this.Error.call(this);
};
},
Recv: function(){
console.log("[recv] "+received_msg);
var buffer = _malloc(received_msg.length + 1);
writeStringToMemory(returnStr, buffer);
return buffer;
},
Error: function(){
console.log("[error] "+error_msg);
var buffer = _malloc(error_msg.length + 1);
writeStringToMemory(error_msg, buffer);
return buffer;
}
}
Inside of ws.onmessage this will refer to ws (as we're inside a method of ws) and not WebsocketLib.
However, inside Initsocket, where you define the handlers, this would correctly (in the sense that this is what you want) refer to the WebsocketLib object, so you can create a bound function to bind the outer this value to be used as this inside the event handler, like this:
ws.onmessage = function(evt) {
received_msg = evt.data;
console.log("[recv] "+received_msg);
this.Recv.call(this);
}.bind(this);
in JavaScript the value of this behaves differently than in other languages. Its value depends on how the function is called. You can read more about it in the Mozilla MDN page.
To solve your specific problem you can:
InitSocket: function(url){
var that = this; // [1]
init_url = Pointer_stringify(url);
console.log("InitWebSocket: "+init_url);
ws = new WebSocket(init_url);
ws.onopen = function(evt){
console.log("Connect");
isConnected = false;
ws.send("hello");
};
ws.onclose = function(evt) {
console.log("Close");
isConnected = false;
};
ws.onmessage = function(evt) {
received_msg = evt.data;
console.log("[recv] "+received_msg);
that.Recv.call(that); // [2]
};
ws.onerror = function(evt) {
error_msg = evt.data;
console.log("[error] "+error_msg);
that.Error.call(that); // [2]
};
},
In line 1 I bind the this variable to a custom variable that I decided to call that (but you can call it as you want). Then in line 2 I used that instead of this.
Inside the ws.onmessage function the value of this is not referring to the instance of WebsocketLib, so you need to use this "trick" and access the right this value using the one saved in the closure, inside the value of that.

Can't save blob to indexedDB

I'm having trouble saving blob in IndexedDB, and only with blob.
If I save something else (like image as base64), everything works fine.
But with blob, there is simply empty object property saved.
Screenshot from console:
Code:
//prepared blob...
var openRequest = indexedDB.open("testDB",1);
openRequest.onupgradeneeded = function(e) {
var thisDB = e.target.result;
if(!thisDB.objectStoreNames.contains("stash")) {
thisDB.createObjectStore("stash");
}
}
openRequest.onsuccess = function(e) {
db = e.target.result;
var transaction = db.transaction(["stash"],"readwrite");
var store = transaction.objectStore("stash");
var tID = Date.now();
var obj = {
bl:blob,
created:tID
}
console.log(obj);
//add it
var request = store.add(obj, tID);
request.onerror = function(e) {
console.log("Error",e.target.error.name);
}
request.onsuccess = function(e) {
console.log("success");
}
}
openRequest.onerror = function(e) {
//....
}
I also tried to save only blob (not wrapped as obj property), it's the same.
I can save blob to HDD, and if I console log my obj, I get:
So I guess, blob is valid, and problem is in adding it to indexedDB. I'm new to blob/indexedDB, and probably doing some noob mistake.
Can someone please advise, what am I doing wrong?
PS: no error messages at all
Very old question, but there is support now for saving Blobs in IndexedDb:
https://developers.google.com/web/updates/2014/07/Blob-support-for-IndexedDB-landed-on-Chrome-Dev
// Create an example Blob object
var blob = new Blob(['blob object'], {type: 'text/plain'});
try {
var store = db.transaction(['entries'], 'readwrite').objectStore('entries');
// Store the object
var req = store.put(blob, 'blob');
req.onerror = function(e) {
console.log(e);
};
req.onsuccess = function(event) {
console.log('Successfully stored a blob as Blob.');
};
} catch (e) {
var reader = new FileReader();
reader.onload = function(event) {
// After exception, you have to start over from getting transaction.
var store = db.transaction(['entries'], 'readwrite').objectStore('entries');
// Obtain DataURL string
var data = event.target.result;
var req = store.put(data, 'blob');
req.onerror = function(e) {
console.log(e);
};
req.onsuccess = function(event) {
console.log('Successfully stored a blob as String.');
};
};
// Convert Blob into DataURL string
reader.readAsDataURL(blob);
}
As of posting this, the referenced Document was last updated on: Last updated 2019-03-20 UTC.
You can convert Blob or File object to ArrayBuffer object or binarystring and then save it. Convert it back to Blob after you read from indexedDB.
//prepared blob...
blobToBlob2(blob, saveBlob2);
function blobToBlob2(blob, callback){
var reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = function(e) {
callback({
buffer: e.target.result,
type: blob.type
});
};
}
function blob2ToBlob(blob2){
return new Blob([blob2.buffer],{type:blob2.type});
}
function saveBlob2(blob2){
//..... code
var obj = {
bl:blob2,
created:tID
}
var request = store.add(obj, tID);
//..... code
}

Using arrays as indexedDB keyPaths in IE 10/11

I have an array as my keypath using indexedDB and it works fine with Chrome and Firefox, but when I try to add/put using IE it gives me a DataError.
var request = window.indexedDB.open("MyTestDatabase");
request.onsuccess = function(event) {
var database = event.target.result;
var transaction = database.transaction(["document"], "readwrite");
var objectStore = transaction.objectStore("document");
var request = objectStore.put({title: 'MyDoc', version: 0});
request.onsuccess = function() {
console.log('document added');
};
request.error = function(error) {
console.log(JSON.stringify(error));
};
transaction.oncomplete = function() {
console.log('transaction complete');
};
transaction.onerror = function(error) {
console.log(JSON.stringify(error));
};
};
request.onupgradeneeded = function(event) {
event.target.result.createObjectStore("document", {keyPath: ['title', 'version']});
};
Error Screenshot:
How can I keep my double keyPath and get it to work with IE?
The only way to get around this at the moment is to create a string out of the array and use it at the key as Kyaw mentioned.
request.onupgradeneeded = function(event) {
event.target.result.createObjectStore("document", {keyPath: ['id']});
};
The id in the example would now have to be a concatenated string containing the title and version. Some like: MyDoc_0. You'd still store the title and version fields though so you can easily access them without have to split the id string.

Categories