По сути, я хочу экспортировать экземпляр класса, у которого есть свойство, содержащее экземпляр базы данных indexedDB, и несколько методов для выполнения операций чтения / записи db. С помощью экспорта я могу provide/inject
этот экземпляр между компонентами в разных деревьях компонентов.
useDb.ts
class DB {
db: IDBDatabase;
constructor(db: IDBDatabase) {
this.db = db;
}
check() {
console.log('checking');
console.log(this.db);
}
// ...other methods...
}
Чтобы получить доступ к экземпляру indexedDB, вам нужно вызвать indexedDB. open () метод. Этот метод является асинхронным, но использует обратные вызовы, а не обещания, и возвращает не экземпляр базы данных, а объект запроса. Чтобы получить фактический экземпляр базы данных, вы присоединяете слушателя к обратному вызову onsuccess:
Пример:
const req = indexedDB.open(DB_NAME, DB_VERSION);
req.onsuccess = (event: Event) => {
const dbInstance = (event.target as IDBOpenDBRequest).result; // Actual instance of db to work with
};
Поскольку он асинхронный, но не использует обещания, я заключаю его в обещание и экспортирую :
useDb.ts
// class DB here...
export default (async () => {
// IndexDB Open request promise-ified
function dbRequest(): Promise<IDBDatabase> {
return new Promise( (resolve, reject) => {
const req = indexedDB.open(DB_NAME, DB_VERSION);
req.onsuccess = (event: Event) => {
const dbInstance = (event.target as IDBOpenDBRequest).result;
resolve(dbInstance);
};
req.onerror = (event: Event) => {
const error = (event.target as IDBOpenDBRequest).error;
reject(error);
}
})
}
// Make sure browser/device supports indexedDb
if(window.indexedDB) {
try {
const dbInstance = await dbRequest();
// Instantiate DB class here passing in the actual database instance to the constructor
const db = new DB(dbInstance);
return db;
} catch(e) {
// TODO: Handle db request error
console.log(e);
return null;
}
} else {
return null;
}
})();
Итак, в моем приложении. vue я мог:
app. vue
import { defineComponent, provide } from '@vue/composition-api'
import useDb from './use/useDb'
export default defineComponent({
name: 'App',
setup() {
provide('db', useDb);
}
})
Проблема, с которой я столкнулся, заключается в том, что поскольку экземпляр db экспортируется как обещание, у меня нет доступа ни к одному из методов экземпляра класса DB. Это не сработает:
random-component. vue
import { defineComponent, inject } from '@vue/composition-api'
export default defineComponent({
name: 'Random',
setup() {
const $db = inject('db');
function testDb() {
$db.check() // Property 'check' does not exist on type 'Promise<DB | null>'.
}
}
})
Я знаю, что могу "$ db.then (db => ...)" в компонентах, но это не похоже на go правильный способ об этом.
Как я могу заставить эту работу работать, или есть лучший способ выполнить sh внедрение зависимостей асинхронной службы?