Issue
I am making a chat application using Ionic 6 and SignalR for test purposes only. I have a chat detail page, and in this page I am listening a BehaviorSubject which triggers from SignalR. Here is my working principle:
- Sender sends a message
- Sender triggers "CheckMessage" in SignalR
- Receiver's SignalR gets it and triggers a BehaviorSubject which I've subscribed on chat detail page.
- It gets the last sent message and show it on the screen.
Everything works as expected, but when I minimise the app and reopen it, after sending/receiving a new message, it shows two times at the screen. When I repeat this, this last message shows at the screen n times (n = how many times that I minimise the app).
How can I solve this issue or what am I missing here?
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(); }
}
Solution
This is happening because in ngOnInit() lifecycly of your detail.component, you get the last message every time it starts:
this.service.getLastMessage(id).pipe(take(1)).subscribe(msg => {
this.messages.push(msg);
});
Solution: before doing this.messages.push(msg)
, (or preferably in you service.getLastMessage()
function) somehow check that if the last message already exists or not, and if not, then add it; something like:
if (!this.messages.includes(msg)) { //better check whith an id, rather than the text
this.messages.push(msg);
}
Answered By - Qiimiia
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.