Как совместить два потока, где второй зависит от первого?

Я создаю приложение, в котором Document имеет, который принадлежит.

Я работаю над основными операциями CRUD для приложения, и мне нужен метод, в котором я получаю поток, но мне также нужно смотреть его.

Проблема в том, что я понятия не имею, как вложить два потока, чтобы при обновлении DocumentTemplate будет обновленный DocumentFamily.

Я был бы очень признателен, если бы кто-нибудь показал мне, как это сделать. Я использую Flutter с ObjectBox в качестве локальной базы данных.

Вот метод, который я начал реализовывать (незавершенный):

      @override
Stream<Either<DocumentTemplateFailure, DocumentTemplate>>
      watchDocumentTemplateById(UniqueId templateId) {
    return _box
        .query(DocumentTemplateEntity_.id.equals(templateId.getOrCrash()))
        .watch(triggerImmediately: true)
        .map((query) {
      final templateEntity = query.findFirst();

      if (null != templateEntity) {
        final familyOrFailureStream =
            _documentFamilyRepository.watchDocumentFamilyById(
                UniqueId.fromUniqueString(templateEntity.familyId));

        familyOrFailureStream.listen((familyOrFailure) {
          return familyOrFailure.fold(
            (failure) =>
                DocumentTemplateFailure.familyFailure(familyFailure: failure),
            (family) => templateEntity.toDomain(family: family),
          );
        });
      }
      return left(const DocumentTemplateFailure.notFound());
    });
  }

И упомянутые выше классы (DocumentTemplate, DocumentTemplateEntity, DocumentFamily и DocumentFamilyEntity):

DocumentTemplate:

      @freezed
class DocumentTemplate with _$DocumentTemplate {
  factory DocumentTemplate({
    required UniqueId id,
    required DocumentTemplateTitle title,
    required double leftMargin,
    required double topMargin,
    required double rightMargin,
    required double bottomMargin,
    required DocumentFamily family,
  }) = _DocumentTemplate;
}

DocumentTemplateEntity:

      @Entity()
class DocumentTemplateEntity {
  @Id()
  int obid = 0;

  @Unique()
  String id;
  String title;
  double leftMargin;
  double topMargin;
  double rightMargin;
  double bottomMargin;
  String familyId;

  DocumentTemplateEntity({
    required this.id,
    required this.title,
    required this.leftMargin,
    required this.topMargin,
    required this.rightMargin,
    required this.bottomMargin,
    required this.familyId,
  });

  DocumentTemplate toDomain({
    required DocumentFamily family,
  }) =>
      DocumentTemplate(
        id: UniqueId.fromUniqueString(id),
        title: DocumentTemplateTitle(title),
        leftMargin: leftMargin,
        topMargin: topMargin,
        rightMargin: rightMargin,
        bottomMargin: bottomMargin,
        family: family,
      );

  factory DocumentTemplateEntity.fromDomain(DocumentTemplate template) =>
      DocumentTemplateEntity(
        id: template.id.getOrCrash(),
        title: template.title.getOrCrash(),
        leftMargin: template.leftMargin,
        topMargin: template.topMargin,
        rightMargin: template.rightMargin,
        bottomMargin: template.bottomMargin,
        familyId: template.family.id.getOrCrash(),
      );
}

DocumentFamily:

      @freezed
class DocumentFamily with _$DocumentFamily {
  factory DocumentFamily({
    required UniqueId id,
    required int position,
    required String name,
  }) = _DocumentFamily;
}

DocumentFamilyEntity:

      @Entity()
class DocumentFamilyEntity {
  @Id()
  int obid = 0;

  @Unique()
  String id;
  String name;
  int position;

  DocumentFamilyEntity({
    required this.id,
    required this.name,
    required this.position,
  });

  DocumentFamily toDomain() => DocumentFamily(
        id: UniqueId.fromUniqueString(id),
        name: name,
        position: position,
      );

  factory DocumentFamilyEntity.fromDomain(DocumentFamily family) =>
      DocumentFamilyEntity(
        id: family.id.getOrCrash(),
        name: family.name,
        position: family.position,
      );
}

Заранее спасибо !

РЕДАКТИРОВАТЬ :

Я попытался решить это самостоятельно и нашел switchMap , который, кажется, объединяет два потока в один, но я не совсем уверен, будет ли он работать, вот обновленный watchDocumentTemplateById метод:

ref.: Как вложить потоки в Dart (сопоставить потоки с событиями Stream)?

        @override
  Stream<Either<DocumentTemplateFailure, DocumentTemplate>>
      watchDocumentTemplateById(UniqueId templateId) {
    return _box
        .query(DocumentTemplateEntity_.id.equals(templateId.getOrCrash()))
        .watch(triggerImmediately: true)
        .switchMap((query) {
      final templateEntity = query.findFirst();
      // if(null == templateEntity) return ??? DocumentTemplateFailure.notFound();
      final familyId = UniqueId.fromUniqueString(templateEntity!.familyId);

      return _documentFamilyRepository.watchDocumentFamilyById(familyId).map(
            (failureOrFamily) => failureOrFamily.fold(
              (failure) => left(
                DocumentTemplateFailure.familyFailure(familyFailure: failure),
              ),
              (family) => right(
                templateEntity.toDomain(family: family),
              ),
            ),
          );
    });
  }

1 ответ

Рассматривали ли вы возможность использования @Entity непосредственно на DocumentFamilyи DocumentTemplateклассы? См. этот пример , который показывает его с пакетом freezed.

В любом случае вам, вероятно, потребуется представить связь между объектами как отношение ObjectBox , а не просто поле идентификатора.

Затем box.query().link() для создания запроса между сущностями. И если вы watch()тот, он срабатывает при изменениях в базовой сущности, а также во всех связанных.

Другие вопросы по тегам