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

附上后端示例:

前端列表:

相关推荐
郝亚军2 小时前
webstorm如何创建vue 3.js
javascript·vue.js·webstorm
用户83134859306984 小时前
Cesium 实现行政区内部遮罩
vue.js·webgl·cesium
卤蛋fg65 小时前
vxe-table 自定义复制粘贴逻辑:精确控制单元格数据转换
vue.js
张人玉7 小时前
基于 Vue 3 + ECharts + Express + SQLite 构建的新能源汽车销量数据分析与可视化平台——新能源汽车销量数据分析系统
数据库·vue.js·sqlite·echarts
清风programmer9 小时前
H5与小程序通信
前端·vue.js·uni-app
Cobyte10 小时前
通过 Vite 运行手写的模板编译器
前端·javascript·vue.js
张人玉10 小时前
基于 Vue 3 + ECharts + Express + SQLite 构—— LDA 模型的新闻舆论主题识别与情感分析系统
vue.js·echarts·express
无人生还10 小时前
从 Vue3 到 React · 快速上手系列第 4 篇:条件渲染与列表渲染
前端·vue.js·react.js
咩咩啃树皮11 小时前
第46篇:Vue3 Router工程化进阶——懒加载+嵌套路由+全局守卫+权限控制
javascript·vue.js·ecmascript
咩咩啃树皮11 小时前
第44篇:Vue3侦听器完全精讲——watch与watchEffect区别、深度监听、异步业务落地
前端·javascript·vue.js