1

我想在视图中显示用户注册的下一个即将发生的事件。

为此,我需要首先检索用户注册的最近事件(及时),然后检索该事件的信息。

用户注册的事件列表是动态的,我需要连续使用两个 Observable 的事件信息也是动态的。

所以我尝试使用 concatMap 但我可以看到 getEvent 函数被调用了 11 次......我不明白为什么以及如何更好地做到这一点。

这是我的控制器

//Controller
    nextEvent$: Observable<any>;

      constructor(public eventService: EventService) {
        console.log('HomePage constructor');
      }

      ngOnInit(): void {
        // Retrieve current user
        this.cuid = this.authService.getCurrentUserUid();
        this.nextEvent$ = this.eventService.getNextEventForUser(this.cuid);
      }

EventService(包含调用 11 次的 getEvent 函数)

// EventService
getEvent(id: string, company?: string): FirebaseObjectObservable<any> {
    let comp: string;
    company ? comp = company : comp = this.authService.getCurrentUserCompany();
    console.log('EventService#getEvent - Getting event ', id, ' of company ', comp);
    let path = `${comp}/events/${id}`;
    return this.af.object(path);
  }

  getNextEventForUser(uid: string): Observable<any> {
    let company = this.authService.getCurrentUserCompany();
    let path = `${company}/users/${uid}/events/joined`;
    let query = {
      orderByChild: 'timestampStarts',
      limitToFirst: 1
    };

    return this.af.list(path, { query: query }).concatMap(event => this.getEvent(event[0].id));
  }

最后是我的观点

<ion-card class="card-background-image">

    <div class="card-background-container">
      <ion-img src="sports-img/img-{{ (nextEvent$ | async)?.sport }}.jpg" width="100%" height="170px"></ion-img>
      <div class="card-title">{{ (nextEvent$ | async)?.title }}</div>
      <div class="card-subtitle">{{ (nextEvent$ | async)?.timestampStarts | date:'fullDate' }} - {{ (nextEvent$ | async)?.timestampStarts | date:'HH:mm' }}</div>
    </div>

    <ion-item>
      <img class="sport-icon" src="sports-icons/icon-{{(nextEvent$ | async)?.sport}}.png" item-left>
      <h2>{{(nextEvent$ | async)?.title}}</h2>
      <p>{{(nextEvent$ | async)?.sport | hashtag}}</p>
    </ion-item>

    <ion-item>
      <ion-icon name="navigate" isActive="false" item-left small></ion-icon>
      <h3>{{(nextEvent$ | async)?.location.main_text}}</h3>
      <h3>{{(nextEvent$ | async)?.location.secondary_text}}</h3>
    </ion-item>

    <ion-item>
      <ion-icon name="time" isActive="false" item-left small></ion-icon>
      <h3>{{(nextEvent$ | async)?.timestampStarts | date:'HH:mm'}} - {{(nextEvent$ | async)?.timestampEnds | date:'HH:mm'}}</h3>
    </ion-item>

  </ion-card>
4

2 回答 2

2

this.af.list(path, { query: query }).concatMap(event => this.getEvent(event[0].id))感冒 Observable。_ 这意味着每次对它执行订阅时,它都会重新执行底层流,也就是重新调用getEvent方法。

async隐式订阅Observable,这就是为什么如果您(nextEvent$ | async)在模板中计算调用次数,您将看到 11 的来源。

&tldr; 您需要共享订阅流:

this.nextEvent$ = this.eventService.getNextEventForUser(this.cuid)
   // This shares the underlying subscription between subscribers
   .share();

上面将在第一次订阅流时连接流,但随后将在所有订阅者之间共享该订阅。

于 2017-05-31T20:33:15.057 回答
0

RXJS 的concatMap方法将所有事件扁平化为一个 observable。switchMap使用该方法可能会更好。switchMap 只订阅最近的 observable。

所以做这样的事情可能会解决你的问题:

前:

return this.af.list(path, { query: query }).concatMap(event => this.getEvent(event[0].id));

后:

return this.af.list(path, { query: query }).switchMap(event => event);

于 2017-05-31T19:36:17.643 回答