html5/javascript.Failed to insert data while using indexedDB - javascript

Here is my code:
function set() {
var db;
var request;
var store;
var username = document.getElementById("username");
var password = document.getElementById("password");
var newuser = {
"username": username.value,
"password": password.value,
};
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
if ('webkitIndexedDB' in window) {
window.IDBTransaction = window.webkitIDBTransaction;
window.IDBKeyRange = window.webkitIDBKeyRange;
}
request = indexedDB.open("userdb", 1);
request.onerror = function(event) {};
request.onsuccess = function(event) {
db = event.target.result;
var transaction = db.transaction(["user"], "readwrite");
var objectStore = transaction.objectStore("user");
var addrequest = objectStore.add(newuser);
addrequest.onsuccess = function(event) {
alert("Success");
};
};
request.onupgradeneeded = function(event) {
db = event.target.result;
store = db.createObjectStore("user", {
keyPath: "username",
autoIncrement: false
});
};
}
After insert data,I use function get() to get data from indexedDB,but I failed to get that,What is the problem?Thank you!
function get() {
var db;
var request;
var store;
var username = document.getElementById("username");
var password = document.getElementById("password");
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
if ('webkitIndexedDB' in window) {
window.IDBTransaction = window.webkitIDBTransaction;
window.IDBKeyRange = window.webkitIDBKeyRange;
}
request = indexedDB.open("userdb", 1);
request.onerror = function(event) {
alert("Error Code:" + event.target.errorCode);
};
request.onsuccess = function(event) {
db = event.target.result;
var transaction = db.transaction("user", IDBTransaction.READ_WRITE);
var objectStore = transaction.objectStore("user");
objectStore.get(username.value);
if (password.value == event.target.result.password)
alert("Success“);
else
alert("Failed");
};
request.onupgradeneeded = function(event) {
alert("Update Success");
};
}
The function works after click another button to get data.But I failed to get data.I have added newuser(username:1 password:1) to the table user.But I cann't get the data.Why?Thank you for your answer.

Your code actually does work, though only once for a given username: after the record has been successfully added to the DB, it persists (which is the point in using IndexedDB in the first place), so subsequent attempts to execute set() result in a fail event on the addrequest object. This never shows up in your code as you haven't defined an onerror handler for said request.
Replace ...
addrequest.onsuccess = function(event) {
alert("Success");
};
... with ...
addrequest.onerror = function(event) {
if (console && console.log) { console.log("add op: Fail\n"); }
};
addrequest.onsuccess = function(event) {
if (console && console.log) { console.log("add op: Success\n"); }
};
... and see it happen (I've taken the liberty to replace alert with console output. Open the console by pressing ctrl-j in the browser window).
Tested on Chrome 50.
Update
Change the get function as follows:
Instead of ...
objectStore.get(username.value);
if (password.value == event.target.result.password)
alert("Success“);
else
alert("Failed");
... write ...
var getrequest = objectStore.get(newuser.username);
getrequest.onerror = function(event) {
if (console && console.log) { console.log("get op: Fail\n"); }
};
getrequest.onsuccess = function(event) {
if (console && console.log) { console.log("get op: Success\n"); }
};
... and it will work.

Related

What in this IndexedDB code is causing the device storage to fill up to 1.6GB?

Our application that utilizes IndexedDB to track tallies of data over periods of time. In using the app for a number of months, it seems that there is some sort of storage leak causing a relatively small amount of data to require 1.6 GB of storage on the device?
The app has a feature to download its full data as a ZIP file, and that file is under 50KB. So there must be a long-term leak somewhere. What we're trying now is to download the data, clear storage, and re-import to track down where this leak might be.
However, looking at the following code that interacts with IndexedDB, it's not obvious to me where that leak may be:
// Initializing the Database
if(!dbengine){
dbengine = this;
var request = window.indexedDB.open("DB", 1);
request.onerror = function(event) {
throw new Error("Error opening indexedDb")
};
// This creates the schema the first time around
request.onupgradeneeded = (event) => {
event.target.result.createObjectStore("db", { keyPath: 'id' });
};
request.onsuccess = (event) => {
dbengine.db = event.target.result;
var dbReadyEvent = new CustomEvent('db-ready', {});
document.dispatchEvent(dbReadyEvent);
dbengine.db.onerror = function(event) {
throw new Error("Database error: " + event.target.errorCode);
};
dbengine.db.onabort = function(event) {
throw new Error("Database aborted: " + event.target.error);
// This is the error that is being called for us - QuotaExceededError
};
};
}// if !dbengine
var initialTransaction = dbengine.db.transaction(['db'], 'readwrite');
initialTransaction.onabort = (event) => {
var error = event.target.error; // DOMError
alert(error.name);
} // onabort
initialTransaction.objectStore('db').openCursor().onsuccess = (event) => {
var cursor = event.target.result;
if(cursor) {
this.encryption.loadIdentity((success) => {
if(success) {
this.loadDb(() => {
document.dispatchEvent(new CustomEvent('api-ready', {}));
setInterval(this.syncDb.bind(this), this.syncInterval);
this.syncDb();
});
} else {
document.dispatchEvent(new CustomEvent('api-fail', {}));
}
});
} else {
initialTransaction.objectStore('db').add({
/* [...] */
});
document.dispatchEvent(new CustomEvent('db-created', {}));
} // if/else cursor
}; // objectStore
loadDb(callback) {
this._tallies = [];
this._collections = [];
var dbStore = dbengine.db.transaction(['db'], 'readwrite').objectStore('db');
dbStore.get(1).onsuccess = (event) => {
var result = event.target.result;
var tallies = result.tallies;
if(result.tallies.length !== 0) {
tallies = this._encryption.decrypt(result.tallies);
}
tallies.forEach(((t) => {
/* [...] */
}));
var collections = result.collections;
if(collections.length !== 0) {
collections = this._encryption.decrypt(result.collections);
}
collections.forEach(((c) => {
/* [...] */
}));
callback()
}
} // loadDb
logout() {
var dbStore = dbengine.db.transaction(['db'], 'readwrite').objectStore('db');
var request = dbStore.get(1);
request.onsuccess = function(e) {
delete e.currentTarget.result.identity;
dbStore.put(e.currentTarget.result);
redirectTo('welcome');
};
} // logout
syncDb() {
var tallyDataString = JSON.stringify(this.tallies);
var collectionDataString = JSON.stringify(this.collections);
var encryptedTallyDataString = this._encryption.encrypt(tallyDataString);
var encryptedCollectionDataString = this._encryption.encrypt(collectionDataString);
var dbStore = dbengine.db.transaction(['db'], 'readwrite').objectStore('db');
dbStore.get(1).onsuccess = (event) => {
var data = event.target.result;
if(data.tallies !== encryptedTallyDataString) {
data.tallies = encryptedTallyDataString;
dbStore.put(data);
}
if(data.collections !== encryptedCollectionDataString) {
data.collections = encryptedCollectionDataString;
dbStore.put(data);
}
var syncEvent = new CustomEvent('sync', {});
document.dispatchEvent(syncEvent);
} // onsuccess
dbStore.get(1).onabort = (event) => {
var error = event.target.error; // DOMError
// if (error.name == 'QuotaExceededError') {
// alert('Sync failed. Quota exceeded.')
// }
alert(error.name);
} // onabort
} // syncDb
loadIdentity(callback) {
var dbStore = dbengine.db.transaction(['db'], 'readwrite').objectStore('db');
dbStore.get(1).onsuccess = (event) => {
var result = event.target.result;
if(!result.identity || !result.identity.publicKey || !result.identity.privateKey) {
if(window.location.pathname !== "/app/welcome/") {
redirectTo('welcome');
}
}
this.identity = {
/* [...] */
};
var solid = false;
if(result.identity.publicKey && result.identity.privateKey) {
solid = true;
}
callback(solid);
};
} // loadIdentity
setIdentity(identity, username) {
var dbStore = dbengine.db.transaction(['db'], 'readwrite').objectStore('db');
var getRequest = dbStore.get(1);
getRequest.onsuccess = (event) => {
var result = event.target.result;
result.identity = {
/* [...] */
};
this.identity = identity;
var request = dbStore.put(result);
} // getRequest
} // setIdentity

RTCmulticonnection getViewers + onjoin event

I'm trying to get the amount of currently viewer of a stream.
I tried to trigger some codes whenever onUserStatusChanged is fired (used as if user onjoin event).
Something like:
connection.onUserStatusChanged = function(status) {
console.log("onUserStatusChanged");
updateViewers();
};
function updateViewers(){
connection.getAllParticipants().forEach(function(participantId) {
var peer = connection.peers[participantId];
if(viewers && viewers.indexOf(peer.extra.nickname) === -1 && "UserA" !== peer.extra.nickname)
viewers.push(peer.extra.nickname);
});
console.log(viewers.length);
}
So far so good it works, But now it pushes also the user who has cam and not watching user A his cam.
I only want the extra.nickname of the user who is connected to User A his cam/channel/connection
Using "beforeAddingStream":
Please download latest codes from github to use this "beforeAddingStream" method.
var listOfStreamReceivers = {};
connection.beforeAddingStream = function(stream, peer) {
var remoteUserExtra = connection.peers[peer.userid].extra;
listOfStreamReceivers[remoteUserExtra.nickname] = peer;
return stream;
};
Using "onExtraDataUpdated" and "updateExtraData"
var listOfStreamReceivers = {};
connection.onstream = function(event) {
if (event.type == 'remote') {
connection.extra.receivedStreamById = event.streamid;
connection.updateExtraData();
}
};
connection.onExtraDataUpdated = function(event) {
if (event.extra.receivedStreamById) {
listOfStreamReceivers[event.extra.nickname] = event;
}
};
Using data channels
connection.session.data = true;
var listOfStreamReceivers = {};
connection.onstream = function(event) {
if (event.type == 'remote') {
var data = {
receivedStreamById: event.streamid
};
// second parameter sends direct message to the broadcast initiator
connection.send(data, connection.sessionid);
}
};
connection.onmessage = function(event) {
if (event.data.receivedStreamById) {
listOfStreamReceivers[event.extra.nickname] = event;
}
};
"listOfStreamReceivers" to array
var array = Object.keys(listOfStreamReceivers);
console.log('number of receivers', array.length);
array.forEach(function(key) {
var peer = listOfStreamReceivers[key];
var userid = peer.userid;
var extra = peer.extra;
});

When using IndexedDB, how can I delete multiple records using an index that is not the key?

I have code to create an indexedDB here:
function create_db() {
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.msIndexedDB;
var request = indexedDB.open(“photos”, 2);
request.onupgradeneeded = function(event) {
var db = event.target.result;
// Create photo db
var photo_store = db.createObjectStore("photos", {keyPath: "photo_id"});
var photo_id_index = photo_store.createIndex("by_photo_id", "photo_id", {unique: true});
var dest_id_index = photo_store.createIndex("by_destination_id", "destination_id");
console.log(“store created”);
};
request.onsuccess = function(event) {
console.log(“store opened”);
};
request.onerror = function(event) {
console.log("error: " + event);
};
}
My code to remove entries:
function remove_photos = function (destination_id, db) {
var transaction = db.transaction("photos", "readwrite");
var store = transaction.objectStore("photos");
var index = store.index("by_destination_id");
var request = index.openCursor(IDBKeyRange.only(destination_id));
request.onsuccess = function() {
var cursor = request.result;
if (cursor) {
cursor.delete();
cursor.continue();
}
};
}
How can I delete records using the by_destination_id index so that I can delete all records with a given destination_id, which is an integer?
Thanks for any help.
I found the solution to my issue, the IDBKeyRange.only function doesn't like integers it needs to be a string, so substituting this line in:
var request = index.openCursor(IDBKeyRange.only(destination_id.toString()));
Make the code work.

db value becomes null or even on indexdb open it does not go into onsuccess or upgradeneeded functions

(function () {
var db;
function openDB(dbname, dbtable, keypath) {
var version = 1;
// open the database
var indexeddb_request = indexedDB.open( dbname, version ); // connect + open database
// if error
indexeddb_request.onerror = function ( event ) {
console.log( event.target );
console.trace();
}
// if success
indexeddb_request.onsuccess = function ( event ) {
console.log( event.target );
console.trace();
db = event.target.result;
}
// if onupgradeneeded
indexeddb_request.onupgradeneeded = function( event ) {
console.log( event.target );
console.trace();
db = event.target.result;
var objectStore = db.createObjectStore( dbtable, { keyPath: 'url' } );
}
}
function getObjectStore(store_name, mode) {
var tx = db.transaction(store_name, mode);
return tx.objectStore(store_name);
}
function addPublication(dbtable, data) {
console.log("addPublication arguments:", arguments);
var store = getObjectStore(dbtable, 'readwrite');
var req;
try {
for (var i in data) {
req = store.add(data[i]);
}
//req = store.add(data);
} catch (e) {
if (e.name == 'DataCloneError')
displayActionFailure("This engine doesn't know how to clone a Blob, " +
"use Firefox");
throw e;
}
req.onsuccess = function (evt) {
console.log("Insertion in DB successful");
};
req.onerror = function() {
console.error("addPublication error", this.error);
};
}
function displayPubList(store, store_name) {
console.log("displayPubList");
if (typeof store == 'undefined')
store = getObjectStore(store_name, 'readonly');
var req;
req = store.count();
// Requests are executed in the order in which they were made against the
// transaction, and their results are returned in the same order.
// Thus the count text below will be displayed before the actual pub list
// (not that it is algorithmically important in this case).
req.onsuccess = function(evt) {
console.log("Count of records " + evt.target.result +
' record(s) in the object store.');
};
req.onerror = function(evt) {
console.error("add error", this.error);
};
var i = 0;
req = store.openCursor();
req.onsuccess = function(evt) {
var cursor = evt.target.result;
// If the cursor is pointing at something, ask for the data
if (cursor) {
console.log("displayPubList cursor:", cursor);
req = store.get(cursor.key);
req.onsuccess = function (evt) {
var value = evt.target.result;
console.log("Key :" + cursor.key + 'value :' + value.ssn );
};
// Move on to the next object in store
cursor.continue();
// This counter serves only to create distinct ids
i++;
} else {
console.log("No more entries");
}
};
}
openDB("abc","names","ssn");
const customerData = [
{ ssn: "444-44-4444", name: "Bill", age: 35, email: "bill#company.com" },
{ ssn: "555-55-5555", name: "Donna", age: 32, email: "donna#home.org" }
];
addPublication("names",customerData);
displayPubList("abc","names");
})();
I'm trying to test the above code from chrome developer tools. But looks like some cases the call goes into sucess or upgradeneeded. And many times its always null. Please let me know if i'm doing something wrong here.

Getting a "setVersion" is not a function error when using indexedDB

I tried to use following code to test the performance of IndexedDB.
The code is modified from http://www.html5rocks.com/en/tutorials/indexeddb/todo/ ,
It works well in chrome, but fails in Firefox 10, saying "db.setVersion is not a function".
I want to know how can I modify the code to make it work in firefox?
var count=0;
var MAX=10;
var times=3;
var allTime;
var stime;
var etime;
var html5rocks = {};
var indexedDB = window.indexedDB || window.webkitIndexedDB ||
window.mozIndexedDB;
if ('webkitIndexedDB' in window) {
window.IDBTransaction = window.webkitIDBTransaction;
window.IDBKeyRange = window.webkitIDBKeyRange;
}
html5rocks.indexedDB = {};
html5rocks.indexedDB.db = null;
html5rocks.indexedDB.onerror = function(e) {
//console.log(e);
alert("Why didn't you allow my web app to use IndexedDB?!");
};
html5rocks.indexedDB.open = function(type) {
var request = indexedDB.open("todos");
request.onsuccess = function(e) {
var v = "1.20";
html5rocks.indexedDB.db = e.target.result;
var db = html5rocks.indexedDB.db;
// We can only create Object stores in a setVersion transaction;
if (v!= db.version) {
var setVrequest = db.setVersion(v);
// onsuccess is the only place we can create Object Stores
setVrequest.onerror = html5rocks.indexedDB.onerror;
setVrequest.onsuccess = function(e) {
if(db.objectStoreNames.contains("todo")) {
db.deleteObjectStore("todo");
}
var store = db.createObjectStore("todo",
{keyPath: "number"});
addTest();
};
}
else addTest();
};
request.onerror = html5rocks.indexedDB.onerror;
}
html5rocks.indexedDB.addTodo = function(todoText,num) {
var db = html5rocks.indexedDB.db;
var trans = db.transaction(["todo"], IDBTransaction.READ_WRITE);
var store = trans.objectStore("todo");
var data = {
"text": todoText,
"number": num
};
var request = store.put(data);
request.onsuccess = function(e) {
count++;
if(count>=times*MAX)
{
etime=new Date;
var t=document.getElementById('result').innerHTML;
document.getElementById('result').innerHTML=t+((etime.valueOf()-stime.valueOf())/times)+"<br/>";
allTime=0;stime=new Date;count=0;
getTest();
}
};
request.onerror = function(e) {
console.log("Error Adding: ", e);
};
};
html5rocks.indexedDB.getTodo = function(id) {
var db = html5rocks.indexedDB.db;
var trans = db.transaction(["todo"], IDBTransaction.READ_WRITE);
var store = trans.objectStore("todo");
var request = store.get(id);
request.onsuccess = function(e) {
count++;
if(count>=times*MAX)
{
etime=new Date;
var t=document.getElementById('result').innerHTML;
document.getElementById('result').innerHTML=t+((etime.valueOf()-stime.valueOf())/times)+"<br/>";
allTime=0;stime=new Date;count=0;
delTest();
}
};
request.onerror = function(e) {
console.log("Error getting: ", e);
};
};
html5rocks.indexedDB.deleteTodo = function(id) {
var db = html5rocks.indexedDB.db;
var trans = db.transaction(["todo"], IDBTransaction.READ_WRITE);
var store = trans.objectStore("todo");
var request = store.delete(id);
request.onsuccess = function(e) {
count++;
if(count>=times*MAX)
{
etime=new Date;
var t=document.getElementById('result').innerHTML;
document.getElementById('result').innerHTML=t+((etime.valueOf()-stime.valueOf())/times)+"<br/>";
allTime=0;stime=new Date;count=0;
dataTest();
}
};
request.onerror = function(e) {
console.log("Error Adding: ", e);
};
};
html5rocks.indexedDB.addData = function(d) {
var db = html5rocks.indexedDB.db;
var trans = db.transaction(["todo"], IDBTransaction.READ_WRITE);
var store = trans.objectStore("todo");
var data={
"text":d,
"number":1
};
var request = store.put(data);
request.onsuccess = function(e) {
etime=new Date;
var t=document.getElementById('result').innerHTML;
document.getElementById('result').innerHTML=t+((etime.valueOf()-stime.valueOf()))+"<br/>";
};
request.onerror = function(e) {
console.log("Error Adding: ", e);
};
};
function addTest() {
for(i=1;i<=times*MAX;i++)
html5rocks.indexedDB.addTodo(' ',i);
}
function getTest() {
for(i=1;i<=times*MAX;i++)
html5rocks.indexedDB.getTodo(Math.round(Math.random()*(MAX*times-1)+1));
}
function delTest() {
for(i=1;i<=times*MAX;i++)
html5rocks.indexedDB.deleteTodo(i);
}
function dataTest() {
data=' ';
for(i=1;i<=21;i++)
data=data+data;
stime=new Date
html5rocks.indexedDB.addData(data);
}
function init() {
stime=new Date;
allTime=0;
html5rocks.indexedDB.open();
}
The spec is not finalized. This is currently shipped as the property mozIndexedDB in Gecko and webkitIndexedDB in Chrome until the standard is finalized. So you have to write for moz also. Now this code is only for webkit.
https://developer.mozilla.org/en/IndexedDB
setVersion() is Deprecated
The new way is to define the version in the IDBDatabase.open() method
firefox from version 10.0 implements open() with the new specification in which an indexeddb database IDBDatabase version is set as the second parameter of the open() method
example
var v = "1.20";
var request = indexedDB.open("todos", v);
html5 indexeddb javascript
The problem here is not the one chosen as the correct answer.
The problem is that the IndexedDB examples on HTML5Rocks were written to the pre-January IndexeDB spec. The working group has since published a breaking change going from the setVersion API to the new onupgradedneeded style.
Here, Firefox is technically correct to fail. Star this issue if you want to see Chrome do the same.

Categories

Resources