Как мне работать со ссылками в Firestore DataConverter? - PullRequest
1 голос
/ 25 марта 2020

Хорошо, поэтому я работаю над проектом (написанным на 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...