我试图“懒得加载”。 Angular 4聊天应用中的消息,它使用Firebase作为其数据集。
这里的想法是在第一次加载应用程序时检索x消息量(现在数量为3以便于调试)并在用户滚动到顶部或按下“更多”消息时加载更多消息。按钮。 我已经编写了一个加载消息的函数:
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 + '.');
});
}
}
问题1:我需要一个' endBefore'而不是' endAt'
这里的第一个问题是' endAt'给我的记录包括' endAt'值:
initial message array = [message 13] [message 14] [message 15]
新消息数组= [消息11] [消息12] [消息13] [消息13] [消息14] [消息15]
我可以限制ToLast(LIMIT_TO_LAST + 1)并删除最后一个对象,但那很难看。这样做的正确方法是什么? 我想到为每条消息添加一个时间戳键(具有毫秒值),按此时间戳键排序,然后说我们想要所有消息为" topMessage.timestamp - 1"。我还没有测试过这是否有效(我不知道endAt键是否必须存在)但是当有2条消息具有完全相同的时间戳时会出现问题,尽管这不太可能,但它可以仍然会发生。
此处不使用limitToLast是一个选项(第一次调用:limitToLast(3),第二次调用:limitToLast(6),依此类推),因为它并不意味着我们只检索3时只显示3条消息。 让我们说我们检索了3条消息,但有人写了一条新消息,它也会被显示(现在我们有4条消息)。如果用户然后按下“loadMore”#39;只会加载2条新邮件而不是3条。 当我们加载3条消息,发送4条消息,然后再检索3条消息时,这个问题会更严重。然后它会删除第一个......
问题2:附加消息列表:
this.messages是一个FirebaseListObservable<>此刻。 据我所知,无法使用新检索的消息附加此列表。 我想创建一个this.messageObjects(或其他东西),包含一组消息对象。每次我检索更多消息时,我都可以附加该数组。 这是一个好主意吗?或者有更好的方法吗?
其他信息
我使用了firebase ID(-K3d - f3e2 ...),所以我不能简单地说'endAt - 1'什么的。
答案 0 :(得分:0)
我现在使用2个对象而不是1个(1个数组,包含消息,1个包含该数组的主题(作为值,而不是引用)。)
当我检索消息时,我将这些附加到数组并使用此数组(作为值,而不是通过引用)调用.next()作为Subject上的参数。这样做了!