vue中使用socket.io统计在线用户

目录

一、引入相关模块

[二、store/modules 中封装socketio](#二、store/modules 中封装socketio)

三、后端代码(nodejs)


一、引入相关模块

main.js 中参考以下代码 ,另外socketio的使用在查阅其它相关文章时有出入,还是尽量以官方文档为准

javascript 复制代码
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

代码如下:

javascript 复制代码
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中

javascript 复制代码
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文件,这个根据个人喜好处理,简单样例代码

javascript 复制代码
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,或者放到表中进行一些其它逻辑的处理

附上后端示例:

前端列表:

相关推荐
今年下半年4 小时前
【VUE】整合腾讯地图、自定义区域边界、村委名称及资产统计(放大显示资产点位)
前端·javascript·vue.js
今年下半年7 小时前
【前端】ant-design-vue 表格「行、列都动态」的处理方案
前端·javascript·vue.js
志尊宝9 小时前
Vue3 零基础每日笔记(054):Pinia 三件套详解——state / getters / actions 全搞懂
前端·javascript·vue.js·vue·前端开发
ym hyd 1119 小时前
慢性病精细化管理平台源码 Java+SpringBoot+Vue3 前后分离
java·vue.js·spring boot·毕设
wangyadong3179 小时前
# el-table 复选框无法选中问题记录
前端·javascript·vue.js
朱 欢 庆10 小时前
el-table 表格组件二次封装
javascript·vue.js·elementui
+VX:Fegn089511 小时前
计算机毕业设计|基于springboot + vue外卖点餐系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
FYKJ_201011 小时前
springboot刑事案件管理系统03047-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·typescript·spark·django
無名路人14 小时前
小程序点餐页吸顶滚动之分类按需加载,上划切换
前端·vue.js·微信小程序
FYKJ_201016 小时前
springboot雅集社区养老管理系统04456-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·typescript·spark·django