目录
一、引入相关模块
main.js 中参考以下代码 ,另外socketio的使用在查阅其它相关文章时有出入,还是尽量以官方文档为准
import VueSocketIO from 'vue-socket.io'
import SocketIO from 'socket.io-client'
const SOCKETIO = new VueSocketIO({
debug: true, // true开启
connection: SocketIO('ws://127.0.0.1:8003',{
autoConnect: false //不自动连接
}),
options: {
transports: ['websocket']
},
vuex: {
store,
actionPrefix: 'SOCKET_',
mutationPrefix: 'SOCKET_'
}
})
Vue.use(SOCKETIO)
二、store/modules 中封装socketio
代码如下:
import io from 'socket.io-client';
import store from '../index';
import moment from 'moment';
let socket = {};
const state = {
socket: {
heartbeatActive: false,
heartbeatInterval: null,
heartbeatTimeout: null,
reconnectAttempts: 0,
maxReconnectAttempts: 5,
},
}
const mutations = {
START_HEARTBEAT(state) {
state.heartbeatActive = true;
},
STOP_HEARTBEAT(state) {
state.heartbeatActive = false;
},
SET_HEARTBEAT_INTERVAL(state, interval) {
state.heartbeatInterval = interval;
},
SET_HEARTBEAT_TIMEOUT(state, timeout) {
state.heartbeatTimeout = timeout;
},
INCREMENT_RECONNECT_ATTEMPTS(state) {
state.reconnectAttempts += 1;
},
RESET_RECONNECT_ATTEMPTS(state) {
state.reconnectAttempts = 0;
}
}
const actions = {
connectSocket({ commit, dispatch }) {
socket=io('http://127.0.0.1:8003'); //socket 服务地址
socket.connect();
socket.on('connect', () => {
console.log('Socket connected');
dispatch('login');
commit('START_HEARTBEAT');
commit('RESET_RECONNECT_ATTEMPTS');
dispatch('startHeartbeat');
});
socket.on('disconnect', () => {
console.log('Socket disconnected');
commit('STOP_HEARTBEAT');
// dispatch('handleReconnect');
});
socket.on('pong', () => {
console.log('Pong received');
clearTimeout(this.state.heartbeatTimeout);
dispatch('resetHeartbeatTimeout');
});
},
login() {
socket.emit('login',{ usercode: store.getters['name'],loginTime: moment().format('YYYY-MM-DD HH:mm:ss') });
},
disconnectSocket({ commit }) {
socket.disconnect();
clearInterval(state.heartbeatInterval);
clearTimeout(state.heartbeatTimeout);
commit('STOP_HEARTBEAT');
},
startHeartbeat({ commit, dispatch }) {
const heartbeatInterval = setInterval(() => {
console.log('user/usercode', store.getters['name'])
//发送心跳包
socket.emit('ping', { usercode: store.getters['name'],lastLoginTime: moment().format('YYYY-MM-DD HH:mm:ss') });
dispatch('resetHeartbeatTimeout');
}, 25000);
commit('SET_HEARTBEAT_INTERVAL', heartbeatInterval);
},
resetHeartbeatTimeout({ commit, state, dispatch }) {
if (state.heartbeatTimeout) {
clearTimeout(state.heartbeatTimeout);
}
const heartbeatTimeout = setTimeout(() => {
console.log('Heartbeat timeout, attempting to reconnect');
dispatch('stopHeartbeat');
dispatch('connectSocket');
}, 30000); // 设置超时时间
commit('SET_HEARTBEAT_TIMEOUT', heartbeatTimeout);
},
stopHeartbeat({ commit, state }) {
clearInterval(state.heartbeatInterval);
clearTimeout(state.heartbeatTimeout);
commit('STOP_HEARTBEAT');
},
handleReconnect({ commit, state, dispatch }) {
if (state.reconnectAttempts < state.maxReconnectAttempts) {
commit('INCREMENT_RECONNECT_ATTEMPTS');
setTimeout(() => {
dispatch('connectSocket');
}, 5000); // 重连间隔
} else {
console.log('Max reconnect attempts reached');
}
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
触发事件写在了AppMain.vue中
export default {
name: 'AppMain',
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews
},
key() {
return this.$route.fullPath
}
},
mounted() {
this.$store.dispatch('socketio/connectSocket'); //登陆成功后手动连接
}
}
三、后端代码(nodejs)
单独封装了一个 socketio.js文件,这个根据个人喜好处理,简单样例代码
global.socketClients= new Map();
global.io.on('connection', (socket) => {
console.log('a user connected');
socket.on('login', (data) => {
console.log('login',data);
global.socketClients.set(data.usercode,data);
console.log(global.socketClients);
});
socket.on('ping', (data) => {
console.log('received heartbeat');
console.log('ping',data);
if(global.socketClients.has(data.usercode)){
global.socketClients.set(data.usercode,_.assign(global.socketClients.get(data.usercode),data));
}else{
global.socketClients.set(data.usercode,data);
}
console.log(global.socketClients);
});
socket.on('disconnect', (reason) => {
if (reason === 'ping timeout') {
console.log('Client disconnected due to heartbeat timeout');
} else {
console.log('Client disconnected due to:', reason);
}
});
});
相关数据可以用redis,或者放到表中进行一些其它逻辑的处理
附上后端示例:
前端列表:
点个赞再走~~