前端(Angular 9)
我正在使用 Socket.io 和 Angular 9 實作聊天功能。創建了一個服務并呼叫了套接字連接和事件處理,如下所示。
@Injectable({
providedIn: 'root',
})
export class ChatService {
private socket;
public channelError = new BehaviorSubject(null);
public channelHistory = new BehaviorSubject(null);
public channelMessage = new BehaviorSubject(null);
public channelReaction = new BehaviorSubject(null);
constructor(
) {}
establishSocketConnection = (userId) => {
this.socket = io(`${chatUrl}/chat`, {
path: '/socket.io',
query: {
user: userId,
},
});
this.socket.on('channel-history', (threads: any) => {
this.channelError.next('');
this.channelHistory.next(threads);
});
this.socket.on('message-local', (message: any) => {
this.channelMessage.next(message);
});
}
// socket (emit) events
public emitMessage = (message, authorId, channel) => {
this.socket.emit('message', message, authorId, channel);
}
public loadChannelHistory = (channelId) => {
this.socket.emit('load-channel-history', channelId);
}
// socket (on) event listeners
public getChannelHistory(): Observable<any> {
return this.channelHistory.asObservable();
}
public getMessage(): Observable<any> {
return this.channelMessage.asObservable();
}
}
我在登錄后呼叫方法“建立套接字連接”一次以建立套接字連接并注冊套接字偵聽器。我已經在此方法中注冊了所有套接字偵聽器。
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { LoginService } from '../../services/login.service';
import { StorageService } from '../../services/storage.service';
import { ProductTypeService } from '../../services/product-type.service';
import { UserSidebarService } from '../../services/user-sidebar.service';
import { Storage } from '@ionic/storage';
import { ChannelTypeService } from 'src/app/services/channel-type.service';
import { ChatService } from 'src/app/services/chat.service';
@Component({
selector: 'app-menu',
templateUrl: './menu.page.html',
styleUrls: ['./menu.page.scss'],
})
export class MenuPage implements OnInit {
activeSettingChild: any;
channelMaintitle: any;
channels: any;
selectedChat: any;
constructor(
private router: Router,
public loginServ: LoginService,
public storageServ: StorageService,
public productTypeServ: ProductTypeService,
public userSidebarServ: UserSidebarService,
public storage: Storage,
private channelTypeServ: ChannelTypeService,
private chatService: ChatService
) {
}
ngOnInit() {
//establish socket connection
let userId = this.storageServ.get('userId');
if (userId) {
this.chatService.establishSocketConnection(userId);
}
this.selectedChat = localStorage.getItem('selectedChat');
this.getAllChannels();
}
getAllChannels() {
this.channelTypeServ.getAllChannelTypes().subscribe(
(channel: any) => {
this.channels = channel.data.channels;
},
(error) => { }
);
}
onSelectChannel(channel) {
this.activeSettingChild = channel.slug;
this.storageServ.set('activeSettingChild', channel.slug);
this.storageServ.set('lockedPageContent', channel.lockedPageContent);
this.storageServ.set('channelTitle', channel.title);
this.storageServ.set('channelId', JSON.stringify(channel));
this.channelMaintitle = channel.settingId.title;
this.storageServ.set('channelMaintitle', this.channelMaintitle);
this.router.navigate(
[`/platinum-chat/${this.selectedChat}/${'channel/' channel.slug}`],
{ replaceUrl: true }
);
}
}
我在一個組件中使用此聊天服務,如下所示。零件:
import { Component, OnInit } from '@angular/core';
import { ChatService } from 'src/app/services/chat.service';
@Component({
selector: 'app-platinum-chat',
templateUrl: './platinum-chat.page.html',
styleUrls: ['./platinum-chat.page.scss'],
})
export class PlatinumChatPage implements OnInit {
message: string;
authorId: any;
channel: any;
threadChat: any[] = [];
channelError: string = '';
constructor(
private chatService: ChatService,
) {
this.channel = localStorage.getItem('channelId');
}
ngOnInit() {
//load channel history
this.loadChannelHistory();
// get new message listener
this.chatService.getMessage().subscribe((msg: any) => {
this.threadChat.push(msg);
});
// error listener
this.chatService.getChannelError().subscribe(errorMessage => {
this.channelError = errorMessage;
});
//channel history listener
this.chatService.getChannelHistory().subscribe((threads: any) => {
this.threadChat = threads;
});
}
loadChannelHistory(){
const channelId = JSON.parse(this.channel);
this.chatService.loadChannelHistory(channelId && channelId._id || null);
}
onSendMessage() {
this.chatService.emitMessage(this.message, this.authorId, this.channel);
}
}
問題是,當我發送新訊息時,它會多次“在訊息本地”呼叫事件偵聽器。正如我已經圍繞這個問題進行了除錯,根據一些建議,重復事件偵聽器注冊存在問題。在我的情況下,我不會多次呼叫方法“建立套接字連接”,然后它是如何注冊重復的偵聽器(訊息本地)并在新訊息上多次呼叫。
注意:不是從服務器端發出的。我只從服務器端發送單個發射,但它在前端被多次呼叫。
在這里我記錄了我的問題 https://www.loom.com/share/d9142c73c6c54cb58802ac3edf704bc5
我不明白當前代碼庫有什么問題。
你們能幫我解決這個問題嗎?提前致謝!!
uj5u.com熱心網友回復:
對于它的價值,不要讓訂閱徘徊。每次加載組件時都會添加訂閱,但不會洗掉。這可能,但可能不是原因。無論如何,我重構并實作了一種取消訂閱()的方法,試一試。
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class PlatinumChatPage implements OnInit, OnDestroy {
message: string;
authorId: any;
channel: any;
threadChat: any[] = [];
channelError: string = '';
subs = [];
constructor(
private chatService: ChatService,
) {
this.channel = localStorage.getItem('channelId');
}
ngOnDestroy() {
this.subs.forEach(sub => sub.unsubscribe());
}
ngOnInit() {
//load channel history
this.loadChannelHistory();
// get new message listener
const chatSub = this.chatService.getMessage().subscribe((msg: any) => {
this.threadChat.push(msg);
});
// error listener
const errorSub = this.chatService.getChannelError().subscribe(errorMessage => {
this.channelError = errorMessage;
});
//channel history listener
const historySub = this.chatService.getChannelHistory().subscribe((threads: any) => {
this.threadChat = threads;
});
this.subs.push(chatSub, errorSub, historySub);
}
loadChannelHistory(){
const channelId = JSON.parse(this.channel);
this.chatService.loadChannelHistory(channelId && channelId._id || null);
}
onSendMessage() {
this.chatService.emitMessage(this.message, this.authorId, this.channel);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/420566.html
標籤:
