嵌套的 Angular/RxJs switchMap 和 Angularfire firebase docData 调用两次而不是一次

问题描述 投票:0回答:1

我在 Angular 中使用 RxJS 有一个复杂的可观察链,并且我面临着嵌套 switchMap 和 docData 调用的意外行为。可观察链涉及使用 docData 使用附加用户数据丰富从 this.stream_service.readFeed() 获取的活动。但是,我在 docData 调用中遇到了意外行为,特别是使用

tap
switchMap
运算符。

我预计 docData next 和 mergeLatest next 日志只会出现一次,因为 Activity_response 数组中只有一项。

尽管有可观察到的发射值,tap 和 switchMap 运算符的记录次数比预期要多。 docData next 和combineLatest next 日志出现两次而不是一次。

这是代码:

private post_activity$ = toObservable(this.post).pipe(
    // Use switchMap to switch to a new observable based on the latest value of post$
    switchMap((post) => {
      // Check if post is falsy (null, undefined, etc.)
      if (!post) {
        // If post is falsy, return an EMPTY observable (essentially a complete and empty observable)
        return EMPTY;
      }

      // Call the current_user() function to get the current user
      const current_user = this.current_user();

      // Determine the feed_type based on whether the current user matches the post's user_id
      const feed_type =
        current_user && current_user?.uid === post.user_id ? 'user' : 'public';

      // Return the result of calling this.stream_service.readFeed()
      return this.stream_service.readFeed(
        feed_type,
        post.user_id,
        1,
        post.stream_activity_id
      );
    }),
    tap((post_activity) => {
      console.log('%cPost Activity', 'color: pink', post_activity);
    }),
    switchMap((activity_response) => {
      // Check if activity_response is falsy
      if (!activity_response) {
        // If it is, return an EMPTY observable
        return EMPTY;
      }
      // Call a service method to enrich the activities in activity_response
      if (activity_response.length > 0) {
        const activity = activity_response[0]; // 1 activity
        console.log('Activity', activity); // This will log once
        return docData(doc(this.firestore, 'users', activity.actor), {
          idField: 'id',
        }).pipe(
          tap({
            next: (user) => console.log('docData next', user),
            error: (error) => console.log('docData error', error),
            complete: () => console.log('docData complete'),
          }), // this will log twice
          switchMap((user: any) => {
            const activity_user = {
              username: user.username,
              pronouns: user.pronouns,
              avatar_url: user.avatar_url,
              photo_url: user.photo_url,
            };
            return of({
              user: activity_user,
              activity: activity,
              liked:
                !!activity.own_reactions?.like &&
                activity.own_reactions.like[0].user_id ===
                  this.user_service.current_user()?.uid,
            });
          }),
          tap({
            next: (activities) => console.log('combineLatest next', activities),
            error: (error) => console.log('combineLatest error', error),
            complete: () => console.log('combineLatest complete'),
          }) // this will log twice too
        );
      } else {
        return EMPTY;
      }
    }),
    tap(() => {
      this.count.set(this.count() + 1);
      console.log('%cCount', 'color: lime', this.count()); // Count 2
    })
  );

可能导致可观察链中出现意外行为的原因以及如何确保 docData next 和 mergeLatest next 日志仅按预期出现一次?

任何有关调试和解决此问题的见解或指导将不胜感激。谢谢!

附加信息:

我添加了一些代码片段来检查隔离它是否会记录 docData() 两次。然而,我最终让事情变得更加令人费解,因为我发现 docData() 不仅只记录一次(如预期),而且我在 switchMap 中的代码也只记录一次。真是令人难以置信!

data$ = docData(
    doc(this.firestore, 'users', activity.actor)
  ).pipe(
    tap({
      next: (user) => console.log('docData next', user),
      error: (error) => console.log('docData error', error),
      complete: () => console.log('docData complete'),
    }) // this will log twice
  );
  private readonly data = toSignal(this.data$);
angular firebase rxjs angularfire rxjs-observables
1个回答
0
投票

经过大量测试,我发现

siwtchMap
函数记录了两次。将其转换为
map
后,它现在仅记录一次。

© www.soinside.com 2019 - 2024. All rights reserved.