附加 FirebaseListObservable 并使用 endAt

Appending FirebaseListObservable and using endAt

我正在尝试 'lazy load' Angular 4 聊天应用程序中的消息,该应用程序使用 Firebase 作为其数据集。

这里的想法是在应用程序第一次加载时检索 x 条消息(现在数量为 3 以便于调试)并在用户滚动到顶部或按下 'more' 按钮时加载更多消息. 我写了一个加载消息的函数:

public retrieveMessages(conversationId, end?) {
  const LIMIT_TO_LAST = 3;
  if (this.firebaseUserIsAuthenticated()) {
    if (end != null) {
      console.log('retrieving next 10');
      this.messages.subscribe(messages => {
        const topMessage = messages[0].$key; 
        console.log('Top message: ' + topMessage);
        const ref = this.firebaseApp.database().ref('messages/' + conversationId);
ref.orderByChild('id').endAt(topMessage).limitToLast(LIMIT_TO_LAST).on('child_added', function (snapshot) { // This gives us the top message + 'LIMIT_TO_LAST'-1 before it
          console.log(snapshot.val());
          messages.unshift(snapshot.val());
        });
        console.log(messages);
      });
    } else {
      console.log('retrieving first 10');
      this.messages = this.db.list('messages/' + conversationId, { query: { limitToLast: LIMIT_TO_LAST } });
    }
    this.messages.subscribe(messages => {
      console.log('Retrieved messages for conversation with id ' + conversationId + '.');
    });
  }
}

Question 1: I need an 'endBefore' instead of 'endAt'

这里的第一个问题是 'endAt' 给我的记录包括具有 'endAt' 值的记录。:

初始消息数组=[消息13][消息14][消息15]

新消息数组=[消息11][消息12][消息13][消息13][消息14][消息15]

我当然可以 limitToLast(LIMIT_TO_LAST + 1) 并删除最后一个对象,但这很难看。这样做的正确方法是什么? 我想到了为每条消息添加一个时间戳键(具有毫秒值),按此时间戳键排序,然后说我们想要 "topMessage.timestamp - 1" 的所有消息。我还没有测试这是否可行(我不知道 endAt 键是否必须存在)但是当有 2 条消息具有完全相同的时间戳时这会产生问题,虽然这不太可能,但它仍然可能发生。

仅使用 limitToLast 在这里不是一个选项(第一次调用:limitToLast(3),第二次调用:limitToLast(6),依此类推),因为这并不意味着我们仅在检索时仅显示 3 条消息3. 假设我们检索到 3 条消息,但有人写了一条新消息,它也会显示(所以现在我们有 4 条消息)。如果用户随后按下 'loadMore',则只会加载 2 条新消息,而不是 3 条。 当我们加载 3 条消息,发送 4 条消息,然后检索“另外 3 条消息”时,这个问题会更糟。然后它将只删除第一个...

Question 2: Appending the list of messages:

this.messages 此时是一个 FirebaseListObservable<>。 据我所知,不可能将此列表附加到新检索到的消息中。 我正在考虑创建一个 this.messageObjects (或其他东西),其中包含一组消息对象。每次我检索更多消息时,我都可以附加该数组。 这是一个好主意吗?或者有更好的方法吗?

Additional info

我使用的是 firebase ID (-K3d--f3e2...),所以我不能简单地说 'endAt - 1' 或其他内容。

我现在使用 2 个对象而不是 1 个(1 个数组,包含消息,1 个包含该数组的主题(作为值,而不是作为参考))。

当我检索消息时,我将它们附加到数组并使用此数组(作为值,而不是通过引用)作为主题的参数调用 .next()。这样就可以了!