Last week I blogged about maxing out the database size on your browser with IndexedDB, but I didn't test with IE. This morning I did, and unfortunately, it looks like IE does the same bad thing it does with LocalStorage (see my post for details).
I discovered that IE11 would silently fail on adding LocalStorage data when the storage limit was reached. Even worse, you could set, and read data that wasn't actually stored. I slightly modified my code from the previous post to make it a bit more verbose. Here is the new version - I'll point out what's new below.
<!doctype html>
<html>
<head>
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
</head>
<body>
<script>
var db;
var dbname = "bighonkingtest2";
var storename = "crap_new";
imgurl = "baby.jpg";
function urlTo64(u, cb) {
var xhr = new XMLHttpRequest();
xhr.open('GET', imgurl, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
// get binary data as a response
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
base64data = reader.result;
cb(base64data);
}
}
};
xhr.send();
}
function indexedDBOk() {
return "indexedDB" in window;
}
document.addEventListener("DOMContentLoaded", function() {
//No support? Go in the corner and pout.
if(!indexedDBOk()) return;
var openRequest = indexedDB.open(dbname,1);
openRequest.onupgradeneeded = function(e) {
var thisDB = e.target.result;
console.log("running onupgradeneeded");
if(!thisDB.objectStoreNames.contains(storename)) {
thisDB.createObjectStore(storename, {keyPath:"id",autoIncrement:true});
}
}
openRequest.onsuccess = function(e) {
console.log("running onsuccess");
db = e.target.result;
console.log("Current Object Stores");
console.dir(db.objectStoreNames);
//Listen for add clicks
document.querySelector("#addButton").addEventListener("click", addData, false);
document.querySelector("#countButton").addEventListener("click", countData, false);
}
openRequest.onerror = function(e) {
//Do something for the error
}
},false);
function addData(e) {
console.log("About to add data");
urlTo64(imgurl, function(s) {
//Get a transaction
//default for OS list is all, default for type is read
var transaction = db.transaction([storename],"readwrite");
transaction.oncomplete = function(e) {
console.log("transaction onsucc");
console.dir(e);
}
transaction.onerror = function(e) {
console.log("transaction onerr");
console.dir(e);
}
//Ask for the objectStore
var store = transaction.objectStore(storename);
//Define data
var data = {
img:s
}
//Perform the add
var request = store.add(data);
request.onerror = function(e) {
console.log("Error",e.target.error.name);
console.dir(e);
//some type of error handler
}
request.onsuccess = function(e) {
console.log("Woot! Did it");
}
});
}
function countData() {
var transaction = db.transaction([storename],"readonly");
var store = transaction.objectStore(storename);
var req = store.count();
req.onsuccess = function(e) {
console.log(req.result + " items.");
}
req.onerror = function(e) {
console.log("error getting count", e);
}
}
</script>
<button id="addButton">Add Data</button>
<button id="countButton">Count Data</button>
</body>
</html>
The first change was to set both the db and objectstore name to variables so I could quickly change them. I then added error/complete handlers to the transaction that handles adding data. Finally, I added a simple "count" method.
To test, I loaded the page up and clicked like crazy. I noticed that at 31 items, the count stopped updating. Here is where things got bad. Before this limit, my transaction complete handler did run. After I hit it, the success handler stopped running, but the onerror method never ran!
I modified the objectStore name and confirmed that in a new store, I could still successfully add data (according to the event handlers) but count was stuck at 0. I had to clear my data in IE settings to get it to let me add data again.
I'll file a bug report for this as soon as I can, but I honestly don't know what to suggest. You could add a timeout call in the add functionality to check for a global variable set in your transaction success. If not set, then it didn't fire and you can assume it failed. That feels quite hackish though.
But hey - this is still better (kinda) than mobile Safari, so, yeah, there's that. ;)