double combLatest не выдает обновления - PullRequest
1 голос
/ 27 мая 2020

В моем проекте есть мероприятия, которые люди создали, присоединились, добавили в закладки или организовали. Я уже прочитал много этих вопросов. Но большая часть кода была менее сложной, или люди забыли подписаться ...

Я хотел бы получить все действия за определенный период времени, а затем добавить информацию о создателе (имя, изображение и т. Д. c) и добавить логические значения, если пользователь, получающий эти действия, присоединился / добавил в закладки / организовал это действие. Код, который я использовал раньше, будет обеспечивать обновления в реальном времени (например, я присоединяюсь к действию, добавляя свой userId в массив участников, и свойство activity.joined обновится до true).

Предыдущий код:

public getActivities(user: UserProfileModel): Observable<Array<ActivityModel>> {
    const now: number = moment().startOf('day').unix();
    const later: number = moment().startOf('day').add(30, 'day').unix();
    return this.afs.collection<ActivityModel>(`cities/${user.city.id}/activities`, ref => ref
        .where('datetime', '>=', now)
        .where('datetime', '<=', later))
        .valueChanges({ idField: 'id' })
        .pipe(
            map(activities => activities.map(activity => {
                const bookmarked = activity.bookmarkers ? activity.bookmarkers.includes(user.uid) : false;
                const joined = activity.participants ? activity.participants.includes(user.uid) : false;
                const organized = activity.organizers ? activity.organizers.includes(user.uid) : false;
                return { bookmarked, joined, organized, ...activity } as ActivityModel;
        }))
    );
}

Я хотел добавить создателя в качестве наблюдаемого объекта, чтобы отображались его последние изменения в имени или аватарке. Но с этим изменением кода мой getActivities больше не выдает никаких обновлений ...

Мой новый код:

public getActivities(user: UserProfileModel): Observable<Array<CombinedActivityCreatorModel>> {
    const now: number = moment().startOf('day').unix();
    const later: number = moment().startOf('day').add(30, 'day').unix();
    return this.afs.collection<ActivityModel>(`cities/${user.city.id}/activities`, ref => ref
        .where('datetime', '>=', now)
        .where('datetime', '<=', later))
        .valueChanges({ idField: 'id' })
        .pipe(
            concatMap(activities => {
                const completeActivityData = activities.map(activity => {
                    const activityCreator: Observable<UserProfileModel> = this.getCreator(activity.creator);
                    const bookmarked = activity.bookmarkers ? activity.bookmarkers.includes(user.uid) : false;
                    const joined = activity.participants ? activity.participants.includes(user.uid) : false;
                    const organized = activity.organizers ? activity.organizers.includes(user.uid) : false;
                    return combineLatest([
                        of({ bookmarked, joined, organized, ...activity }),
                        activityCreator
                    ]).pipe(
                        map(([activityData, creatorObject]: [ActivityModel, UserProfileModel]) => {
                            return {
                                 ...activityData,
                                 creatorObject: creatorObject
                            } as CombinedActivityCreatorModel;
                        })
                    );
                });
            return combineLatest(completeActivityData);
        })
    );
}

Код стал немного сложным, что я не решение вижу сам. Кто-нибудь может предложить помощь?

1 Ответ

1 голос
/ 28 мая 2020

Похоже, что один из activityCreator не генерирует значение, combLatest требует, чтобы все наблюдаемые испускались хотя бы один раз.

Я бы порекомендовал вам отладить, как ведет себя activityCreator. Если нормально, что он не генерирует, у вас есть 2 варианта: startWith, чтобы установить значение для начального испускания, или defaultIfEmpty, он испускает в случае, если поток будет закрыт без какого-либо испускания.

activityCreator = this.getCreator(activity.creator).pipe(
  // startWith(null), // for example if you want to trigger combineLatest.
  // defaultIfEmpty(null), // in case of an empty stream.
);

другая вещь - concatMap для завершения требуется наблюдаемое, только затем он переключается на следующий, возможно, mergeMap или switchMap здесь лучше.

Попробуйте код ниже и добавьте его вывод в комментарии. Спасибо.

                        const activityCreator: Observable<UserProfileModel> = this.getCreator(activity.creator).pipe(
                            tap(
                                () => console.log('getCreator:emit'),
                                () => console.log('getCreator:error'),
                                () => console.log('getCreator:completed'),
                            ),
                        );
...