【发布时间】:2022-01-25 03:38:40
【问题描述】:
前端(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();
}
}
我在登录后调用方法“建立套接字连接”一次以建立套接字连接并注册套接字侦听器。我已经在这个方法中注册了所有的socket监听器。
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
我不明白当前代码库有什么问题。
你们能帮我解决这个问题吗?提前致谢!!
【问题讨论】:
-
您是否可以在 stackblitz 上创建一个最小的工作示例?
-
还包括显示消息的 html 的相关部分。
标签: angular socket.io angular9