Skip to main content

消息中心

以在vue中使用为例

MessageCenter部分

MessageCenter的实现其实是对mitt库的简单封装,如果不依赖库则需要自己实现一个发布订阅模式,这种方式在vue中通常被称之为事件总线,EventBus

npm i mitt

MessageCenter.ts内容

import mitt from "mitt";
const MessageCenter = mitt();
export default MessageCenter;

使用,与angular中的消息中心差不多,需要指定事件名称

  • main.ts里引入MessageCenter.ts
import MessageCenter from './api/message-center';
  • 在页面任何位置引入并通过emit发送消息
import MessageCenter from '../../api/message-center';
function sentMessageByMitt() {
MessageCenter.emit('globalMessage', { code: '1111', name: 'demo组件发出的' })
}
  • 在页面任何位置引入并通过on接收消息
import MessageCenter from './api/message-center';
MessageCenter.on('globalMessage', (data) => {
console.log('-----', data);
})

注意,在不需要的时候请将订阅关闭,防止出现内存溢出

onUnmounted(() => {
MessageCenter.off('globalMessage')
})

ReWebSocketService部分

ReWebSocketService是对reconnecting-websocket的简单封装,由于在封装原生websocket中对服务断开重连之后,暂无思路处理连接改变无法接收到消息的问题,所以采用了reconnecting-websocket

websocket的使用主要还是依赖提供的服务,其次约定前后端交互数据格式

  • 前端使用
import { ReWebSocketService } from '../../api/re-web-socket-service';
/**交互的数据格式 */
interface WebSocketMsg {
/**传入ip则根据ip发消息,否则广播 */
ip?: Array<string>,
/**同个ip,多个账户请传入 */
userName?: string,
data: any
}
// 接收到消息时的回调
const messageCallback = (e) => {
console.log('接收websocket消息', e)
}
// new 对象时候根据需要传入对应时间的回调函数openCallback, messageCallback, errorCallback, closeCallback
const reWebSocketService: ReWebSocketService = new ReWebSocketService('ws://192.168.12.106:3001', {
messageCallback: messageCallback
});
// 不需要的时候将连接断开,避免内存溢出
onUnmounted(() => {
reWebSocketService.websocket.close();
})
// 发送消息
function sentMessageBywebsocket() {
const data: WebSocketMsg = {
ip: ['192.168.12.110'],// 传入ip则表示单播
data: '来自106的消息'
}
reWebSocketService.websocket.send(JSON.stringify(data))
}
  • 后端服务,这里用node.js实现,具体项目有组长决定
const ws = require("nodejs-websocket")

let count=0;
const server = ws.createServer(function (conn) {
count++;
console.log("有新的连接"+count);
const ipAndPort=conn.headers.origin.substring(7).split(':');
conn.userName='用户'+count;
conn.ip=ipAndPort[0];
conn.port=ipAndPort[1];
// 有连接时广播通知
broadcast({count:count,currUserIp:ipAndPort[0],currUserName:conn.userName,data:'登录成功'});
conn.on("text", (data)=> {
const result=JSON.parse(data);
if(result&&result.ip){// 有ip则单播
server.connections.forEach(conn=>{
result.ip.forEach(ip=>{
if(conn.ip===ip){
conn.sendText(JSON.stringify({
count:count,
currUserIp:ipAndPort[0],
currUserName:conn.userName,
data:result.data
}))
}
})
})
}else{
broadcast({count:count,currUserIp:ipAndPort[0],currUserName:conn.userName,data:result.data});
}
})
conn.on("close", (code, reason)=> {
console.log("有人关闭");
count--;
// broadcast('gunabi')
})
conn.on("error", (err)=> {
console.log(err, "连接报错");
});
}).listen(3001,()=>console.log('服务启动成功,端口3001'));
/**广播 */
function broadcast(data) {
server.connections.forEach( (connection) =>{
connection.sendText(JSON.stringify(data));
})
}