В javascript у меня есть класс для обработки запросов. Я хочу убедиться, что у меня все правильно настроено для обработки ошибок. Я хочу открыть соединение с БД и закрыть его при каждом запросе. У меня есть этот код до сих пор
export default class IndexedDBStorage {
#name:string;
constructor(name:string) {
this.#name = name;
}
private async GetDB():Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
// https://javascript.info/indexeddb
const request = window.indexedDB.open(this.#name, 1);
request.onupgradeneeded = () => {
//this.#db = request.result;
if (!request.result.objectStoreNames.contains(this.#name)) {
request.result.createObjectStore(this.#name, {keyPath: 'id', autoIncrement:true});
}
};
request.onerror = () => {
reject("Why didn't you allow my web app to use IndexedDB?! " + request.error?.code);
};
request.onsuccess = () => {
//request.result.onerror = () => {
// Generic error handler for all errors targeted at this database's requests!
// reject("Database error: " + request.error?.code);
//};
resolve(request.result);
};
});
}
async GetAllItems<T>():Promise<Array<T>> {
return new Promise((resolve, reject) => {
this.GetDB().then(db => {
const transaction = db.transaction(this.#name);
const store = transaction.objectStore(this.#name);
const datarequest = store.getAll();
db.close();
datarequest.onsuccess = function() {
resolve(datarequest.result);
};
datarequest.onerror = function() {
reject("Error " + datarequest.error);
};
}).catch(err => {
console.error(err);
});
});
}
}
Также хотелось узнать, чем отличается эта часть внутри функции GetDB
. Это событие onerror самой базы данных, которое настраивается в событии onsuccess.
//request.result.onerror = () => {
// Generic error handler for all errors targeted at this database's requests!
// reject("Database error: " + request.error?.code);
//};
И эта часть
datarequest.onerror = function() {
reject("Error " + datarequest.error);
};
?
Спасибо
Обновлено:
export default class IndexedDBStorage {
#name:string;
constructor(name:string) {
this.#name = name;
}
private async GetDB():Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const request = window.indexedDB.open(this.#name, 1);
request.onerror = (event: Event) => {
// this function catches all errors
// all errors in database, transaction or request levels should be caught and handled there
const errorEvent = event as Event & {error:string};
console.error(errorEvent.error);
alert(errorEvent.error);
reject(errorEvent.error);
};
request.onblocked = function () {
// this event shouldn't trigger if we handle onversionchange correctly
// it means that there's another open connection to the same database
// and it wasn't closed after db.onversionchange triggered for it
const message = 'Database is currently blocked, page needs to reload, click ok to reload.';
alert(message);
window.location.reload();
//console.info(message);
//reject(message);
};
request.onupgradeneeded = (event: IDBVersionChangeEvent) => {
const db = request.result;
console.info('idb onupgradeneeded firing');
switch(event.oldVersion) { // existing db version
case 0:
// version 0 means that the client had no database
// perform initialization
console.info('Database currently at version 0 which means that the client had no database');
console.info(`Upgrading to version ${db.version}`);
request.result.createObjectStore(this.#name, {keyPath: 'id', autoIncrement:true});
case 1:
// client had version 1
// update
console.info('Database currently at version 1 which means that the database already exists');
}
};
request.onsuccess = () => {
const db = request.result;
db.onversionchange = function() {
db.close();
const message = "Database is outdated, page needs to reload, click ok to reload.";
alert(message);
window.location.reload();
};
resolve(db);
};
});
}
async GetAllItems<T>():Promise<Array<T>> {
return new Promise((resolve, reject) => {
this.GetDB().then(db => {
const transaction = db.transaction(this.#name);
const store = transaction.objectStore(this.#name);
const datarequest = store.getAll();
db.close();
datarequest.onsuccess = function() {
resolve(datarequest.result);
};
}).catch(err => {
reject(err);
});
});
}
}
На самом деле это хороший пример проблем с этим «антипаттерном конструктора обещаний»: GetAllItems
никогда не урегулируется (ни разрешится, ни отклонится), если this.GetDB()
отклонит.
@Bergi Как я могу это исправить? Я не очень понимаю из вашей ссылки, как это исправить.
В основном return this.getDb().then(db => { return new Promise((resolve, reject) => { … }); }).catch(…)
. Хотя вам, вероятно, следует удалить .catch(console.error) , и если getDb()
возвращает базу данных, которую всегда нужно закрывать, вы можете использовать шаблон disposer.
error
со значением
Избегайте антипаттерна конструктора обещаний ! Создайте
new Promise
только для каждого запроса, но в противном случае используйте цепочку промисов.