同时调用的 Firestore 查询 "onSnapshot" 不起作用(
Firestore query "onSnapshot" called at the same time does not work (
我使用 Ionic 和 Firestore 创建了一个具有实时聊天功能的应用程序,但我遇到了问题。
会话加载方法:
refUneConversationMyUserCol.ref.orderBy('date', 'desc').limit(20).get()
为此添加了一个“onSnapshot”请求以检索实时发送的最后一条消息
this.unsubscribeDataUneConversation = refUneConversationMyUserCol.ref.orderBy('date', 'desc').limit(1).onSnapshot(result => {
console.log(result.docs[0].data());
if (this.isCalledBySnapshot === false) {
this.isCalledBySnapshot = true;
} else if (result.docs[0].data().expediteur !== this.authentificationService.uidUserActif) {
const data = result.docs[0].data();
const id = result.docs[0].id;
this.dataUneConversation.push({ id, ...data } as UneConversation);
}
});
它会完美地工作,但是,当我同时发送一条消息时(有 2 个不同的帐户相互通信),我遇到了一个问题,onSnapshot 只被触发一次,我只收到一条消息。
我指定这两条消息在数据库中发送得很好,只是在实时会话中它们都没有显示
你知道为什么吗?
谢谢
(这里是整个方法)
async getDataUneConversation(idI: string) {
if (this.loadedDataUneConversation !== idI) {
/* ANCHOR Msg en direct */
this.isCalledBySnapshot = false;
if (this.unsubscribeDataUneConversation) {
await this.unsubscribeDataUneConversation();
}
const refUneConversationMyUserCol = this.afs.collection<User>('users').doc<User>(this.authentificationService.uidUserActif).collection<Conversations>('conversations');
const result = await refUneConversationMyUserCol.ref.orderBy('date', 'desc').limit(20).get();
/* ANCHOR Msg en direct */
this.unsubscribeDataUneConversation = refUneConversationMyUserCol.ref.orderBy('date', 'desc').limit(1).onSnapshot(result => {
console.log(result.docs[0].data());
if (this.isCalledBySnapshot === false) {
this.isCalledBySnapshot = true;
} else if (result.docs[0].data().expediteur !== this.authentificationService.uidUserActif) {
const data = result.docs[0].data();
const id = result.docs[0].id;
this.dataUneConversation.push({ id, ...data } as UneConversation);
}
});
/* ANCHOR Msg en brut */
if (result.docs.length < 20) {
this.infiniteLastUneConversationMax = true;
} else {
this.infiniteLastUneConversationMax = false;
}
this.infiniteLastUneConversation = result.docs[result.docs.length - 1];
this.dataUneConversation = result.docs.map(doc => {
const data = doc.data();
const id = doc.id;
return { id, ...data } as UneConversation;
});
this.dataUneConversation.reverse();
this.loadedDataUneConversation = idI;
}
}
编辑工作:
this.unsubscribeDataUneConversation = refUneConversationMyUserCol.ref.orderBy('date', 'asc').startAfter(this.dataUneConversation[this.dataUneConversation.length
- 1].date).onSnapshot(result => {
result.docs.forEach(element => {
const data = element.data();
const id = element.id;
if (!this.dataUneConversation.some(e => e.id === element.id)) {
this.dataUneConversation.push({ id, ...data } as UneConversation);
}
});
});
您将实时消息限制为仅最后一条消息。在聊天应用程序中,您想收听所有新消息。所以问题可能出在你的 .limit(1)
子句中。
但如果您这样做,我知道您将获得自对话开始以来的整个对话以及所有消息。
我的做法是这样的:
- 从您的
refUneConversationMyUserCol...
对话加载器获取最后一条消息的日期。
- 当您执行 onSnapshot() 以获取最后一条消息时,不限制为 1 条 条消息,相反,从日期之后的日期开始最后加载的消息.
由于您无论如何都是按日期订购的,所以这很容易解决。查看“Adding a cursor to your query”。
基本上,您会对 Firestore 说:给我实时新消息,但从现在开始 - 即使同时发布了很多消息,您也会得到所有消息,因为您不是限制为 1.
如果这还不够清楚,请随时询问。
我使用 Ionic 和 Firestore 创建了一个具有实时聊天功能的应用程序,但我遇到了问题。
会话加载方法:
refUneConversationMyUserCol.ref.orderBy('date', 'desc').limit(20).get()
为此添加了一个“onSnapshot”请求以检索实时发送的最后一条消息
this.unsubscribeDataUneConversation = refUneConversationMyUserCol.ref.orderBy('date', 'desc').limit(1).onSnapshot(result => {
console.log(result.docs[0].data());
if (this.isCalledBySnapshot === false) {
this.isCalledBySnapshot = true;
} else if (result.docs[0].data().expediteur !== this.authentificationService.uidUserActif) {
const data = result.docs[0].data();
const id = result.docs[0].id;
this.dataUneConversation.push({ id, ...data } as UneConversation);
}
});
它会完美地工作,但是,当我同时发送一条消息时(有 2 个不同的帐户相互通信),我遇到了一个问题,onSnapshot 只被触发一次,我只收到一条消息。
我指定这两条消息在数据库中发送得很好,只是在实时会话中它们都没有显示
你知道为什么吗?
谢谢
(这里是整个方法)
async getDataUneConversation(idI: string) {
if (this.loadedDataUneConversation !== idI) {
/* ANCHOR Msg en direct */
this.isCalledBySnapshot = false;
if (this.unsubscribeDataUneConversation) {
await this.unsubscribeDataUneConversation();
}
const refUneConversationMyUserCol = this.afs.collection<User>('users').doc<User>(this.authentificationService.uidUserActif).collection<Conversations>('conversations');
const result = await refUneConversationMyUserCol.ref.orderBy('date', 'desc').limit(20).get();
/* ANCHOR Msg en direct */
this.unsubscribeDataUneConversation = refUneConversationMyUserCol.ref.orderBy('date', 'desc').limit(1).onSnapshot(result => {
console.log(result.docs[0].data());
if (this.isCalledBySnapshot === false) {
this.isCalledBySnapshot = true;
} else if (result.docs[0].data().expediteur !== this.authentificationService.uidUserActif) {
const data = result.docs[0].data();
const id = result.docs[0].id;
this.dataUneConversation.push({ id, ...data } as UneConversation);
}
});
/* ANCHOR Msg en brut */
if (result.docs.length < 20) {
this.infiniteLastUneConversationMax = true;
} else {
this.infiniteLastUneConversationMax = false;
}
this.infiniteLastUneConversation = result.docs[result.docs.length - 1];
this.dataUneConversation = result.docs.map(doc => {
const data = doc.data();
const id = doc.id;
return { id, ...data } as UneConversation;
});
this.dataUneConversation.reverse();
this.loadedDataUneConversation = idI;
}
}
编辑工作:
this.unsubscribeDataUneConversation = refUneConversationMyUserCol.ref.orderBy('date', 'asc').startAfter(this.dataUneConversation[this.dataUneConversation.length
- 1].date).onSnapshot(result => {
result.docs.forEach(element => {
const data = element.data();
const id = element.id;
if (!this.dataUneConversation.some(e => e.id === element.id)) {
this.dataUneConversation.push({ id, ...data } as UneConversation);
}
});
});
您将实时消息限制为仅最后一条消息。在聊天应用程序中,您想收听所有新消息。所以问题可能出在你的 .limit(1)
子句中。
但如果您这样做,我知道您将获得自对话开始以来的整个对话以及所有消息。
我的做法是这样的:
- 从您的
refUneConversationMyUserCol...
对话加载器获取最后一条消息的日期。 - 当您执行 onSnapshot() 以获取最后一条消息时,不限制为 1 条 条消息,相反,从日期之后的日期开始最后加载的消息.
由于您无论如何都是按日期订购的,所以这很容易解决。查看“Adding a cursor to your query”。
基本上,您会对 Firestore 说:给我实时新消息,但从现在开始 - 即使同时发布了很多消息,您也会得到所有消息,因为您不是限制为 1.
如果这还不够清楚,请随时询问。