【问题标题】:Angular Firebase listen to foreach changes with subscribeAngular Firebase 通过 subscribe 监听 foreach 的变化
【发布时间】:2019-06-28 20:05:58
【问题描述】:

我订阅获取用户聊天,然后对于每个聊天,我订阅另外两个 observables。

get_user_chat(chat) {
    let user = this.firebase.get_user_by_uid(chat.key).snapshotChanges();
    let chatInfo = this.firebase.get_single_chat(chat.payload.val()).snapshotChanges();
    return Observable.forkJoin(user.take(1), chatInfo.take(1));
}

getChats() {
//start loading
let loading = this.loadingCtrl.create();
loading.present();

//get chats
this.firebase.get_user_chats().snapshotChanges().takeUntil(this.ngUnsubscribe).subscribe(chats => {
  chats.forEach(chat => {
    this.get_user_chat(chat).takeUntil(this.ngUnsubscribe).subscribe(userChat => {
      this.userChat = userChat;
      this.user = this.userChat[0];
      this.chat = this.userChat[1];

      this.chats.push({
        firstName: this.user.payload.val().firstName,
        imageUrl: this.user.payload.val().imageUrl,
        uid: this.user.key,
        chatId: chat.payload.val(),
        last_message: this.chat.payload.val().last_message.message,
        type: this.chat.payload.val().last_message.type
      })
    })
  })
  //dimiss loading
  loading.dismiss();
}, err => {
  //dimiss loading
  loading.dismiss();
})

}

现在对于前端,我正在显示这样的数据:

<ion-content>
  <ion-list class="chat-list" *ngIf="(chats)?.length>0">
    <a ion-item detail-none *ngFor="let c of chats" (click)="toChat(c.chatId, c.uid)">
      <ion-thumbnail item-start>
        <img-loader class="img-logo" src={{c.imageUrl}} fallbackUrl="assets/img/placeholder-person.png" useImg></img-loader>
      </ion-thumbnail>
      <h2>{{c.firstName}}</h2>
      <h3 *ngIf="c.type!='img'">{{c.last_message}}</h3>
      <img class="img-placeholder" *ngIf="c.type=='img'" src="assets/img/placeholder-image.png">
      <!-- <ion-icon item-right name="ios-arrow-forward"></ion-icon> -->
    </a>
  </ion-list>
  <ion-card *ngIf="(chats)?.length==0">
    <ion-card-content>
      You don't have any chats.
    </ion-card-content>
  </ion-card>
</ion-content>

除了聊天最后一条消息不会在前端自动更新之外,这是可行的,我理解为什么这不起作用,我将观察者推入一个数组,该数组失去了监听更改的功能,但我不能不知道如何在不从两个不同的订阅者推送对象的情况下收听更改并正确显示它们。我基本上每次都要重新加载聊天列表才能看到变化。

最好用图片来说明:

Holly 的最后一条消息是“a”

我向 Holly 发送了另一条消息,最后一条消息现在应该是“B”

但是如果不刷新页面,最后一条消息不会更新,它不会监听更改,因为我正在将 observable 推送到数组中

1:1 聊天的 Firebase 实时数据库结构

用户 1:

用户 2:

聊天室:

【问题讨论】:

    标签: javascript firebase firebase-realtime-database observable angularfire


    【解决方案1】:

    我强烈建议将每个聊天室建模为 Firestore 中的一个集合。这样,如果您有一个用于 Brendan 和 Holly 之间聊天的聊天室/集合,那么您只能从一个集合中读取,而不是两个。这也使得以正确的顺序保持消息更容易,因为您可以使用单个查询来获取它们。

    有关这方面的示例,请参阅Best way to manage Chat channels in Firebase。虽然这个问题是关于实时数据库的,但同样的逻辑也可以应用于 Cloud Firestore。

    【讨论】:

    • 我想我做过类似的事情,用户以聊天用户 id 作为键和聊天室键作为值进行聊天,但是您仍然需要从“用户”获取用户信息和来自“聊天”的聊天信息,因为这只是键和值,没有其他信息。否则我必须将这些信息(聊天名字,最后一条消息)放入用户聊天中,并且当用户更改他的名字或最后一条消息更改时,我将不得不更新几个地方,这在我理解的 firebase 中很好,但它变得如此更复杂,我已经更新了我的问题。
    • 这种结构实际上让我很困惑,你想如何在不再次调用获取用户信息(如姓名、性别等)的情况下获取用户信息,列表仅包含用户 ID以 true 作为值。
    • 如果您有用户信息和聊天消息,您通常会保留两个顶级列表:一个用于用户信息,另一个用于聊天消息。您需要进行客户端加入,以获取用户信息。您还可以将一些用户信息复制到每个聊天消息中,或者在另一个顶级列表中设置一个单独的节点,其中包含房间的所有元数据。但最重要的是,您的聊天消息存储为单个列表,因此您不会尝试分别加载来自每个用户的消息。
    • 通过扫描您的数据模型,您似乎正试图在每个聊天室中显示最新消息。这应该通过每个聊天室上的limitToLast() 侦听器来完成,或者也可以将每个房间的最后一条消息保留在“房间元数据”中。后者在写入操作上更复杂,但使读取更简单,因为您只需要一个侦听器,因此不需要两个列表的(失败)合并。
    • 推荐一个场外资源无论如何都是题外话,这就是为什么我在上一条评论中给你最常用的选项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2021-07-07
    • 2016-07-15
    相关资源
    最近更新 更多