I'm trying to write a class that returns methods to work with indexedDB (I need a reusable API to share with the rest of my web app).
This is what my constructor looks like so far:
const IndexDbParams = {
// Update this when changing the db schema
dbVersion: 1,
// Database, object store names
databaseName: "CropViewData",
fieldsObjectStoreName: "fieldsData",
filedObjectStoreKeyName: "key",
zoneMapObjectStoreName: "zoneMapData"
};
class IndexDbClient {
constructor() {
this.initializeDB().then(db => (this.db = db));
}
async initializeDB() {
return new Promise((resolve, reject) => {
const {
dbVersion,
databaseName,
fieldsObjectStoreName,
filedObjectStoreKeyName
} = IndexDbParams;
// Open a connection to indexDB
const DbOpenRequest = window.indexedDB.open(databaseName, dbVersion);
DbOpenRequest.onsuccess = e => {
const db = DbOpenRequest.result;
// Create data stores if none exist
if (db.objectStoreNames.length < 1) {
if (db.objectStoreNames.indexOf(fieldsObjectStoreName) < 0) {
db.createObjectStore(fieldsObjectStoreName, {
keyPath: filedObjectStoreKeyName
});
}
}
// return db object, will come hore from onupgradeneeded as well
resolve(db);
};
// If we need to upgrade db version
DbOpenRequest.onupgradeneeded = e => {
const db = event.target.result;
const objectStore = db.createObjectStore(fieldsObjectStoreName, {
keyPath: filedObjectStoreKeyName
});
};
});
}
getFieldData(compareFunction, queryParams) {
return new Promise((resolve, reject) => {
const { fieldsObjectStoreName } = IndexDbParams;
const transaction = this.db.transaction(
fieldsObjectStoreName,
"readonly"
);
// If db transaction fails, reject
transaction.onerror = e => {
reject(transaction.error);
};
const objectStore = transaction.objectStore(fieldsObjectStoreName);
const cursor = objectStore.openCursor();
// const to store query results
const results = [];
cursor.onsuccess = event => {
const result = cursor.result;
// If we have a entry
if (result) {
// evaluate function here
if (compareFunction(queryParams, result)) {
// Add the entry to the results array
results.push(result.value);
}
// If we have no more entries
} else {
// Return all results
resolve(results);
}
};
cursor.onerror = event => {
reject(cursor.error);
};
});
}
getFieldById(fieldId) {
return new Promise((resolve, reject) => {
this.getFieldData(this.byId, { id: fieldId })
.then(data => {
resolve(data);
})
.catch(e => {
reject(e);
});
});
}
byId({ id }, field) {
return field.id === id;
}
}
export default IndexDbClient;
Then I am importing the client in another file (my store):
import IndexDbClient from "../facades/IndexDbClient";
const db = new IndexDbClient();
db.getFieldById("fe276ead-def3-47a6-aefd-020e844774af").then(res => {
console.log(res);
});
And I get an error:
Uncaught (in promise) TypeError: Cannot read property 'transaction' of undefined
If I run the same function from the console, the error is not there. I assume that this is due to the constructor not assigning the db object to the IndexDbClient yet? Is there a way for me to work around this - The way I see it I have to wait for the .onsucess
event in the initializeDB()
method in order to be sure the indexedDB connection is open?