当前位置:首页 » 《资源分享》 » 正文

Vue2 使用WebSocket实现前端与后端的实时通讯

11 人参与  2024年03月29日 09:40  分类 : 《资源分享》  评论

点击全文阅读


功能描述:WebSocket是一种在单个TCP连接上进行全双工通信的协议,它能够在客户端和服务器之间建立持久的连接,使得实时通讯成为可能。在前端开发中,WebSocket通常用于实现实时消息推送、实时数据更新等功能,为用户提供更流畅、即时的体验

本文将介绍如何在前端项目中利用WebSocket实现与后端的实时通讯,并结合具体的代码示例进行讲解。

实现单例模式的SocketService类

在本文中,我们将使用一个名为SocketService的类来封装WebSocket的相关操作,并通过单例模式确保在整个应用程序中只有一个SocketService实例存在。这样可以避免多次实例化和重复连接服务器的问题,同时方便在应用程序的不同模块中共享同一个SocketService实例,实现统一的数据传输和处理逻辑。

创建utils文件夹--->websocket.js文件

import { LoginWebSocketApi } from "@/request/api";export default class SocketService {    // 用于实现单例模式的写法    // 可以确保在整个应用程序中只有一个SocketService实例存在,避免了多次实例化和重复连接服务器的问题。通过单例模式,可以方便地在应用程序的不同模块中共享同一个SocketService实例,实现统一的数据传输和处理逻辑。    static instance = null;    static get Instance() {        if (!this.instance) {            this.instance = new SocketService()        }        return this.instance    }    ws = null    // 标识是否连接成功    connected = false    // 重试的次数    sendRetryCount = 0    // 重连的次数    connectRetryCount = 0    // 存储回调函数    // callBackMapping = {}    heartbeatInterval = null;    // 连接服务器的方法    connect(vue) {        // 连接服务器        if (!window.WebSocket) {            return console.log("浏览器不支持webSocket")        }        if (!localStorage.getItem("token")) {            console.log('没有token,不连接WebSocket');            return;        }        this.ws = new WebSocket("wss://你的地址");        // 连接成功的事件        this.ws.onopen = () => {            console.log("连接成功");            this.connected = true;            this.connectRetryCount = 0;            clearTimeout(this.heartbeatInterval);            this.start();        }        // 连接失败的事件        this.ws.onclose = () => {            console.log("连接失败")            this.connected = false;            if (this.connectRetryCount <= 100) {                this.connectRetryCount++            }            setTimeout(() => {                this.connect(vue)            }, this.connectRetryCount * 500)        }        // 收到数据的事件        this.ws.onmessage = (res) => {            // console.log("获取信息", res.data)            try {                console.log('接收消息', res.data);                let data_arr = JSON.parse(res.data);                let type = data_arr.type;                // 处理不同类型的消息                switch (type) {                    case 'login':                        this.login_websocket(data_arr.client_id);                        break;                    case 'charge_normal_end':                        vue.$bus.$emit('charge_normal_end', data_arr);                        break;                    case 'shots_count_change':                        vue.$bus.$emit('shots_count_change', data_arr);                        break;                    default:                        break;                }            } catch (e) {                console.log('e', e);            }        }    }    login_websocket(client_id) {        LoginWebSocketApi({            client_id: client_id,            ws_group: '首页'        }).then((webRes) => {            let ddd = {                type: 'login_success',                login_id: webRes.data.login_id            };            this.send(JSON.stringify(ddd));            console.log('发送登录消息', ddd);            this.manual_colse = false;        }).catch((err) => {            console.log('33err', err)        });    }    // 发送    send(data) {        // this.ws.send(data)        if (this.connected) {            this.sendRetryCount = 0;            this.ws.send(data)        } else {            this.sendRetryCount++            setTimeout(() => { }, this.sendRetryCount * 500)        }    }    // 关闭socket连接    close() {        if (this.ws) {            this.ws.close();            this.connected = false; // 更新连接状态            clearInterval(this.heartbeatInterval); // 清除心跳检测定时器        }    }    // 开启心跳检测    start() {        this.heartbeatInterval = setInterval(() => {            this.data = {                type: "ping"            };            this.send(JSON.stringify(this.data));        }, 5000);    }}

注意点:在webSocket.js这样的非Vue组件文件中,this并不指向Vue实例,因此无法直接通过this.$bus来访问事件总线,所以我这用的是vue.$bus.$emit.

在main.js文件中:我的事件总线是挂载在Vue原型上的,那么我在组件中就可以使用this.$bus来访问它

Vue.use(ElementUI);new Vue({  router,  store,  render: h => h(App),  beforeCreate() {    Vue.prototype.$bus = this  }}).$mount('#app')

在App.vue文件里的mounted生命周期钩子中执行,在登录成功后调用了SocketService.Instance.connect(this)来连接WebSocket。

<script>import SocketService from "./utils/websocket";import { AutoLoginApi } from "@/request/api";export default {  mounted() {    const token = localStorage.getItem("token");    if (token) {      AutoLoginApi()        .then(res => {          if (token) {            SocketService.Instance.connect(this);          }        })        .catch(error => {          console.log("自动登录error", error);        });    }  }};</script>

在需要监听数据的页面进行this.$bus.$on监听, this.$bus.$off 移除自定义事件监听器。

<script>export default {  data() {    return {    };  },  beforeDestroy() {    console.log("销毁");    this.stopListening();  },  created() {    this.startListening();  },  methods: {    startListening() {      this.$bus.$on("charge_normal_end", this.on_res_msg_charge_normal_end);      this.$bus.$on("shots_count_change", this.on_res_msg_shots_count_change);    },    stopListening() {      this.$bus.$off("charge_normal_end", this.on_res_msg_charge_normal_end);      this.$bus.$off("shots_count_change", this.on_res_msg_shots_count_change);    },    on_res_msg_charge_normal_end(data) {      //在这里处理逻辑      console.log("输出信息查看", data);    },    on_res_msg_shots_count_change(data) {      console.log("输出信息查看", data);    }  }};</script>

最后,在退出登录的时候,关闭webSocket

<script>import SocketService from "@/utils/websocket";export default {  data() {    return {          };  },  methods: {    // 退出登录    handleCommand(command) {     // 清除token        localStorage.removeItem("token");     // 关闭WebSocket连接        if (SocketService.Instance.connected) {          console.log("关闭WebSocket连接");          SocketService.Instance.ws.close();        }    }  }};</script>


点击全文阅读


本文链接:http://zhangshiyu.com/post/87465.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 祖母寿宴,侯府冒牌嫡女被打脸了(沈屿安秦秀婉)阅读 -
  • 《雕花锦年,昭都旧梦》(裴辞鹤昭都)完结版小说全文免费阅读_最新热门小说《雕花锦年,昭都旧梦》(裴辞鹤昭都) -
  • 郊区41号(许洛竹王云云)完整版免费阅读_最新全本小说郊区41号(许洛竹王云云) -
  • 负我情深几许(白诗茵陆司宴)完结版小说阅读_最热门小说排行榜负我情深几许白诗茵陆司宴 -
  • 九胞胎孕妇赖上我萱萱蓉蓉免费阅读全文_免费小说在线看九胞胎孕妇赖上我萱萱蓉蓉 -
  • 为保白月光,侯爷拿我抵了债(谢景安花田)小说完结版_完结版小说全文免费阅读为保白月光,侯爷拿我抵了债谢景安花田 -
  • 陆望程映川上官硕《我的阿爹是带攻略系统的替身》最新章节阅读_(我的阿爹是带攻略系统的替身)全章节免费在线阅读陆望程映川上官硕
  • 郑雅琴魏旭明免费阅读_郑雅琴魏旭明小说全文阅读笔趣阁
  • 头条热门小说《乔书意贺宴临(乔书意贺宴临)》乔书意贺宴临(全集完整小说大结局)全文阅读笔趣阁
  • 完结好看小说跨年夜,老婆初恋送儿子故意出车祸_沈月柔林瀚枫完结的小说免费阅读推荐
  • 热推《郑雅琴魏旭明》郑雅琴魏旭明~小说全文阅读~完本【已完结】笔趣阁
  • 《你的遗憾与我无关》宋怀川冯洛洛无弹窗小说免费阅读_免费小说大全《你的遗憾与我无关》宋怀川冯洛洛 -

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1