0


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

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

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

实现单例模式的SocketService类

在本文中,我们将使用一个名为

  1. SocketService

的类来封装WebSocket的相关操作,并通过单例模式确保在整个应用程序中只有一个

  1. SocketService

实例存在。这样可以避免多次实例化和重复连接服务器的问题,同时方便在应用程序的不同模块中共享同一个

  1. SocketService

实例,实现统一的数据传输和处理逻辑。

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

  1. import { LoginWebSocketApi } from "@/request/api";
  2. export default class SocketService {
  3. // 用于实现单例模式的写法
  4. // 可以确保在整个应用程序中只有一个SocketService实例存在,避免了多次实例化和重复连接服务器的问题。通过单例模式,可以方便地在应用程序的不同模块中共享同一个SocketService实例,实现统一的数据传输和处理逻辑。
  5. static instance = null;
  6. static get Instance() {
  7. if (!this.instance) {
  8. this.instance = new SocketService()
  9. }
  10. return this.instance
  11. }
  12. ws = null
  13. // 标识是否连接成功
  14. connected = false
  15. // 重试的次数
  16. sendRetryCount = 0
  17. // 重连的次数
  18. connectRetryCount = 0
  19. // 存储回调函数
  20. // callBackMapping = {}
  21. heartbeatInterval = null;
  22. // 连接服务器的方法
  23. connect(vue) {
  24. // 连接服务器
  25. if (!window.WebSocket) {
  26. return console.log("浏览器不支持webSocket")
  27. }
  28. if (!localStorage.getItem("token")) {
  29. console.log('没有token,不连接WebSocket');
  30. return;
  31. }
  32. this.ws = new WebSocket("wss://你的地址");
  33. // 连接成功的事件
  34. this.ws.onopen = () => {
  35. console.log("连接成功");
  36. this.connected = true;
  37. this.connectRetryCount = 0;
  38. clearTimeout(this.heartbeatInterval);
  39. this.start();
  40. }
  41. // 连接失败的事件
  42. this.ws.onclose = () => {
  43. console.log("连接失败")
  44. this.connected = false;
  45. if (this.connectRetryCount <= 100) {
  46. this.connectRetryCount++
  47. }
  48. setTimeout(() => {
  49. this.connect(vue)
  50. }, this.connectRetryCount * 500)
  51. }
  52. // 收到数据的事件
  53. this.ws.onmessage = (res) => {
  54. // console.log("获取信息", res.data)
  55. try {
  56. console.log('接收消息', res.data);
  57. let data_arr = JSON.parse(res.data);
  58. let type = data_arr.type;
  59. // 处理不同类型的消息
  60. switch (type) {
  61. case 'login':
  62. this.login_websocket(data_arr.client_id);
  63. break;
  64. case 'charge_normal_end':
  65. vue.$bus.$emit('charge_normal_end', data_arr);
  66. break;
  67. case 'shots_count_change':
  68. vue.$bus.$emit('shots_count_change', data_arr);
  69. break;
  70. default:
  71. break;
  72. }
  73. } catch (e) {
  74. console.log('e', e);
  75. }
  76. }
  77. }
  78. login_websocket(client_id) {
  79. LoginWebSocketApi({
  80. client_id: client_id,
  81. ws_group: '首页'
  82. }).then((webRes) => {
  83. let ddd = {
  84. type: 'login_success',
  85. login_id: webRes.data.login_id
  86. };
  87. this.send(JSON.stringify(ddd));
  88. console.log('发送登录消息', ddd);
  89. this.manual_colse = false;
  90. }).catch((err) => {
  91. console.log('33err', err)
  92. });
  93. }
  94. // 发送
  95. send(data) {
  96. // this.ws.send(data)
  97. if (this.connected) {
  98. this.sendRetryCount = 0;
  99. this.ws.send(data)
  100. } else {
  101. this.sendRetryCount++
  102. setTimeout(() => { }, this.sendRetryCount * 500)
  103. }
  104. }
  105. // 关闭socket连接
  106. close() {
  107. if (this.ws) {
  108. this.ws.close();
  109. this.connected = false; // 更新连接状态
  110. clearInterval(this.heartbeatInterval); // 清除心跳检测定时器
  111. }
  112. }
  113. // 开启心跳检测
  114. start() {
  115. this.heartbeatInterval = setInterval(() => {
  116. this.data = {
  117. type: "ping"
  118. };
  119. this.send(JSON.stringify(this.data));
  120. }, 5000);
  121. }
  122. }

注意点:在

  1. webSocket.js

这样的非Vue组件文件中,

  1. this

并不指向Vue实例,因此无法直接通过

  1. this.$bus

来访问事件总线,所以我这用的是vue.$bus.$emit.

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

  1. this.$bus

来访问它

  1. Vue.use(ElementUI);
  2. new Vue({
  3. router,
  4. store,
  5. render: h => h(App),
  6. beforeCreate() {
  7. Vue.prototype.$bus = this
  8. }
  9. }).$mount('#app')

在App.vue文件里的

  1. mounted

生命周期钩子中执行,在登录成功后调用了

  1. SocketService.Instance.connect(this)

来连接WebSocket。

  1. <script>
  2. import SocketService from "./utils/websocket";
  3. import { AutoLoginApi } from "@/request/api";
  4. export default {
  5. mounted() {
  6. const token = localStorage.getItem("token");
  7. if (token) {
  8. AutoLoginApi()
  9. .then(res => {
  10. if (token) {
  11. SocketService.Instance.connect(this);
  12. }
  13. })
  14. .catch(error => {
  15. console.log("自动登录error", error);
  16. });
  17. }
  18. }
  19. };
  20. </script>

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

  1. <script>
  2. export default {
  3. data() {
  4. return {
  5. };
  6. },
  7. beforeDestroy() {
  8. console.log("销毁");
  9. this.stopListening();
  10. },
  11. created() {
  12. this.startListening();
  13. },
  14. methods: {
  15. startListening() {
  16. this.$bus.$on("charge_normal_end", this.on_res_msg_charge_normal_end);
  17. this.$bus.$on("shots_count_change", this.on_res_msg_shots_count_change);
  18. },
  19. stopListening() {
  20. this.$bus.$off("charge_normal_end", this.on_res_msg_charge_normal_end);
  21. this.$bus.$off("shots_count_change", this.on_res_msg_shots_count_change);
  22. },
  23. on_res_msg_charge_normal_end(data) {
  24. //在这里处理逻辑
  25. console.log("输出信息查看", data);
  26. },
  27. on_res_msg_shots_count_change(data) {
  28. console.log("输出信息查看", data);
  29. }
  30. }
  31. };
  32. </script>

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

  1. <script>
  2. import SocketService from "@/utils/websocket";
  3. export default {
  4. data() {
  5. return {
  6. };
  7. },
  8. methods: {
  9. // 退出登录
  10. handleCommand(command) {
  11. // 清除token
  12. localStorage.removeItem("token");
  13. // 关闭WebSocket连接
  14. if (SocketService.Instance.connected) {
  15. console.log("关闭WebSocket连接");
  16. SocketService.Instance.ws.close();
  17. }
  18. }
  19. }
  20. };
  21. </script>

本文转载自: https://blog.csdn.net/zengkeai/article/details/134691084
版权归原作者 zengkeai 所有, 如有侵权,请联系我们删除。

“Vue2 使用WebSocket实现前端与后端的实时通讯”的评论:

还没有评论