Хорошо, поэтому я работаю над проектом (написанным на TypeScript с использованием Vue) с использованием Firestore, и я предпочитаю подход, основанный на моделях, к данным, поэтому я создал классы для представления всех моих моделей. Я связываю некоторые из этих моделей, используя ссылки, поэтому мне не нужно хранить 300 документов с одинаковыми данными. Поскольку я использую подход, основанный на моделях, я решил использовать Firestore FirestoreDataConverter
, чтобы помочь мне получать свои данные из базы данных и из нее.
Проблема, с которой я сейчас работаю в том, что я не могу написать асинхронную функцию fromFirestore
и вернуть Promise
, потому что Typescript продолжает жаловаться, что возвращаемые типы на fromFirestore
не совпадают, потому что я возвращаю обещание. Код для одного полного класса (с некоторыми незначительными изменениями), перечисленного ниже.
import { firestore } from 'firebase/app';
import {
AdministrativeArea,
AdministrativeAreaSchema,
AdministrativeAreaConverter
} from './administrative-area';
import {
Country,
CountryCollection,
CountrySchema,
CountryConverter,
} from './country';
import { Model } from './model';
export interface AddressSchema {
administrativeArea: firestore.DocumentReference<AdministrativeAreaSchema>;
country: firestore.DocumentReference<CountrySchema>;
locality: string;
postalCode: string;
premise?: string;
subAdministrativeArea?: string;
subPremise?: string;
thoroughfare: string;
}
export interface AddressViewModel {
administrativeArea: AdministrativeArea;
country: Country;
id?: string;
locality: string;
postalCode: string;
premise?: string;
subAdministrativeArea?: string;
subPremise?: string;
thoroughfare: string;
}
export class Address extends Model {
private _administrativeArea: AdministrativeArea;
private _country: Country;
private _locality: string;
private _postalCode: string;
private _premise?: string;
private _subAdministrativeArea?: string;
private _subPremise?: string;
private _thoroughfare: string;
constructor(opts: AddressViewModel) {
super(opts.id);
this._administrativeArea = opts.administrativeArea;
this._country = opts.country;
this._locality = opts.locality;
this._postalCode = opts.postalCode;
this._premise = opts.premise;
this._subAdministrativeArea = opts.subAdministrativeArea;
this._subPremise = opts.subPremise;
this._thoroughfare = opts.thoroughfare;
}
public get administrativeArea(): AdministrativeArea {
return this._administrativeArea;
}
public get country(): Country {
return this._country;
}
public get locality(): string {
return this._locality;
}
public get postalCode(): string {
return this._postalCode;
}
public get premise(): string {
return this._premise ? this._premise : '';
}
public get subAdministrativeArea(): string {
return this._subAdministrativeArea ? this._subAdministrativeArea : '';
}
public get subPremise(): string {
return this._subPremise ? this._subPremise : '';
}
public get thoroughfare(): string {
return this._thoroughfare;
}
}
export const AddressConverter = {
toFirestore(address: Address): firestore.DocumentData {
return {
administrativeArea: CountryCollection
.doc(address.country.id)
.collection('administrativeAreas')
.doc(address.administrativeArea.id),
country: CountryCollection.doc(address.country.id),
locality: address.locality,
postalCode: address.postalCode,
premise: address.premise,
subAdministrativeArea: address.subAdministrativeArea,
subPremise: address.subPremise,
thoroughfare: address.thoroughfare,
};
},
async fromFirestore(snapshot: firestore.QueryDocumentSnapshot<AddressSchema>,
options?: firestore.SnapshotOptions): Promise<Address> {
const data = snapshot.data(options);
const countrySnap = await data.country
.withConverter(CountryConverter)
.get();
const country = countrySnap.data() as Country;
const adminAreaSnap = await data.administrativeArea
.withConverter(AdministrativeAreaConverter)
.get();
const administrativeArea = adminAreaSnap.data() as AdministrativeArea;
return Promise.resolve(
new Address({
administrativeArea,
country,
id: snapshot.id,
locality: data.locality,
postalCode: data.postalCode,
premise: data.premise,
subAdministrativeArea: data.subAdministrativeArea,
subPremise: data.subPremise,
thoroughfare: data.thoroughfare,
})
);
},
};
РЕДАКТИРОВАТЬ: я забыл упомянуть, что в качестве пробела, пока я не могу найти решение, я просто делаю пустой do / пока петли. Например:
let country: Country | null = null;
data.country
.withConverter(CountryConverter)
.get()
.then((res) => {
country = country.data() as Country;
});
do ; while (country === null)