我正在使用 Ionic 6 和 SignalR 制作一个聊天应用程序,仅用于测试目的。我有一个聊天详细信息页面,在该页面中我正在监听从 SignalR 触发的BehaviorSubject。这是我的工作原理:
一切都按预期进行,但是当我最小化应用程序并重新打开它时,在发送/接收新消息后,它在屏幕上显示两次。当我重复此操作时,最后一条消息会在屏幕上显示 n 次(n = 我最小化应用程序的次数)。
我该如何解决这个问题或者我在这里缺少什么?
signalR.cs:
public async Task CheckMessage(int chatId)
{
try
{
await Clients.OthersInGroup("group-" + chatId.ToString()).SendAsync("NewMessage", chatId);
}
catch (Exception ex)
{
await _log.InsertErrorLog(ex);
}
}
app.component.ts:
constructor(....) {
App.addListener("appStateChange", result => {
if (result.isActive) {
this.signalR.createHubConnection();
} else {
this.signalR.stopHubConnection();
}
});
}
ngOnDestroy(): void {
App.removeAllListeners();
}
signalR.service.ts:
createHubConnection() {
this.hubConnection = new HubConnectionBuilder()
.withUrl(this.hubUrl + 'URL?SOME_PARAMETERS', {
accessTokenFactory: () => USER_TOKEN
})
.withAutomaticReconnect()
.build();
this.hubConnection.start();
this.hubConnection.on('NewMessage', id => {
this.zone.run(() => {
this.v.newChatMessage$.next(id);
});
});
}
stopHubConnection() {
if (this.hubConnection) {
this.hubConnection.stop();
}
}
async checkNewMessages(id: number) {
return this.hubConnection.invoke('CheckMessage', id);
}
v.component.ts:
newChatMessage$: Subject<number> = new BehaviorSubject(0);
detail.component.ts:
sub: Subscription;
ngOnInit() {
if (this.sub == undefined) {
this.sub = this.v.newChatMessage$.subscribe(id => {
if (id > 0 && id == this.chat.id) {
this.service.getLastMessage(id).pipe(take(1)).subscribe(msg => {
this.messages.push(msg);
this.scrollToBottom();
});
this.v.newChatMessage$.next(0);
}
})
}
}
sendMessage() {
this.service.addMessage(MESSAGE_ITEM).pipe(take(1)).subscribe(result => {
this.messages.push(result);
this.signalR.checkNewMessages(this.chat.id);
this.scrollToBottom();
});
}
ngOnDestroy(): void {
if (this.sub) { this.sub.unsubscribe(); }
}
发生这种情况是因为在detail.component 的 ngOnInit() 生命周期中,每次启动时您都会收到最后一条消息:
this.service.getLastMessage(id).pipe(take(1)).subscribe(msg => {
this.messages.push(msg);
});
解决方案:在执行
this.messages.push(msg)
之前(或者最好在您的 service.getLastMessage()
函数中)以某种方式检查最后一条消息是否已经存在,如果不存在,则添加它;像这样的东西:
if (!this.messages.includes(msg)) { //better check whith an id, rather than the text
this.messages.push(msg);
}