侧边栏壁纸
博主头像
一笑痕

仙人之下我无敌,
仙人之上一换一。

  • 累计撰写 8 篇文章
  • 累计收到 8 条评论

Vue3中的WebSocket使用

2025-3-23 / 1 评论 / 44 阅读

WebSocket 是一种在客户端和服务器之间进行全双工通信的协议。它提供了一种实时、持久的连接方式,可以用于实现实时数据更新、即时通讯等功能。在 Vue 3 中,可以通过 WebSocket API 来实现与服务器的 WebSocket 连接。

常见使用场景

WebSocket 在实时通信和推送场景中非常常见,以下是一些常见的使用场景:

  1. 实时聊天应用程序:通过 WebSocket 可以实现实时的双向通信,用于构建在线聊天室或即时通讯应用。
  2. 实时数据更新:通过 WebSocket 可以实时获取服务器端的数据更新,例如股票行情、即时新闻等。
  3. 多人协作编辑:通过 WebSocket 可以实现多人协作编辑功能,多个用户可以同时编辑同一文档并实时同步修改。
  4. 实时游戏:通过 WebSocket 可以实现多人实时游戏,实现玩家之间的实时通信和状态同步。

安装依赖

首先,需要安装 vue-native-websocket 库,它提供了在 Vue 中使用 WebSocket 的功能。

npm install vue-native-websocket

创建 WebSocket 实例

在 Vue 3 中,可以在组件中通过 setup 函数创建 WebSocket 实例,并将其添加到组件的上下文中。

import { ref, onMounted, onUnmounted } from 'vue';
import { useWebSocket } from 'vue-native-websocket';

export default {
  setup() {
    const socket = useWebSocket('wss://xxxx/socket');

    // 监听连接事件
    onMounted(() => {
      socket.value.onopen = () => {
        console.log('WebSocket connected');
      };
    });

    // 监听消息事件
    const message = ref('');
    socket.value.onmessage = (event) => {
      message.value = event.data;
    };

    // 监听关闭事件
    onUnmounted(() => {
      socket.value.onclose = () => {
        console.log('WebSocket disconnected');
      };
    });

    return {
      message,
    };
  },
};

在上面的例子中,通过 useWebSocket 函数创建了一个 WebSocket 实例,并指定了要连接的 WebSocket 地址。使用 onMounted 钩子来监听连接事件,当 WebSocket 连接成功时,打印出一条消息。还使用 onUnmounted 钩子来监听关闭事件,当 WebSocket 连接关闭时,打印出一条消息。

发送消息

可以通过 WebSocket 实例的 send 方法来发送消息到服务器。

socket.value.send('Hello, server!');

在上面的例子中,通过 send 方法发送了一条消息到服务器。

常用方法

1. 连接错误

如果连接失败,可以通过 onerror 事件处理错误。

socket.value.onerror = (event) => {
  console.error('WebSocket error:', event);
};

通过 onerror 事件处理连接错误,并将错误信息打印到控制台。

2. 重新连接

如果 WebSocket 连接断开,可以通过重新创建 WebSocket 实例来重新连接。

socket.value.onclose = () => {
  console.log('WebSocket disconnected');
  // 重新连接
  socket.value = useWebSocket('wss://example.com/socket');
};

通过 onclose 事件监听连接关闭,并在连接关闭时重新创建 WebSocket实例来重新连接。

3. 心跳机制

为了保持 WebSocket 连接的活跃状态,可以使用心跳机制定期发送心跳消息。

// 心跳消息
const heartbeatMessage = 'ping';

// 定时发送心跳消息
setInterval(() => {
  socket.value.send(heartbeatMessage);
}, 5000);

// 监听消息事件
socket.value.onmessage = (event) => {
  const message = event.data;
  if (message === heartbeatMessage) {
    // 收到心跳消息,做相应处理
  } else {
    // 处理其他消息
  }
};

定期发送心跳消息,并在收到心跳消息时进行相应处理。

使用 Vuex 进行 WebSocket 状态管理

在复杂的应用中,可能需要在多个组件之间共享 WebSocket 的连接状态和接收到的消息。这时,可以使用 Vuex 进行 WebSocket 状态的管理。

首先,需要安装 vuex

npm install vuex

然后,创建一个 websocket 模块来管理 WebSocket 的状态。

// store/modules/websocket.js
const state = {
  socket: null,
  message: '',
};

const mutations = {
  SET_SOCKET(state, socket) {
    state.socket = socket;
  },
  SET_MESSAGE(state, message) {
    state.message = message;
  },
};

const actions = {
  connect({ commit }) {
    const socket = useWebSocket('wss://xxxxx/socket');

    socket.value.onopen = () => {
      console.log('WebSocket connected');
    };

    socket.value.onmessage = (event) => {
      commit('SET_MESSAGE', event.data);
    };

    socket.value.onclose = () => {
      console.log('WebSocket disconnected');
    };

    commit('SET_SOCKET', socket);
  },
  sendMessage({ state }, message) {
    state.socket.value.send(message);
  },
};

export default {
  state,
  mutations,
  actions,
};

然后,在主 store 文件中导入和注册该模块。

// store/index.js
import { createStore } from 'vuex';
import websocket from './modules/websocket';

export default createStore({
  modules: {
    websocket,
  },
});

现在,可以在组件中使用 mapState mapActions 辅助函数来访问 WebSocket 的状态和发送消息。

<template>
  <div>
  <p>Message: {{ message }}</p>
  <button @click="sendMessage">Send Message</button>
  </div>
  </template>

  <script>
  import { mapState, mapActions } from 'vuex';

export default {
  computed: {
    ...mapState('websocket', ['message']),
  },
  methods: {
    ...mapActions('websocket', ['connect', 'sendMessage']),
  },
  mounted() {
    this.connect();
  },
};
</script>

使用 mapState 辅助函数将 websocket 模块的 message 状态映射到组件的计算属性,使用 mapActions 辅助函数将 websocket 模块的 connect sendMessage 方法映射到组件的方法。在组件的 mounted 钩子中调用 connect 方法来建立 WebSocket 连接。

常见问题处理

1. 跨域问题

当使用 WebSocket 连接到不同域的服务器时,可能会遇到跨域问题。为了解决这个问题,服务器需要设置适当的 CORS 头部。

2. 断线重连

在 WebSocket 连接断开的情况下,可以通过在 onclose 事件中重新建立连接来实现断线重连。

socket.value.onclose = ()=> {
  setTimeout(() => {
    connect();
  }, 3000);
};

使用 setTimeout 函数在连接断开后等待 3 秒钟重新建立连接。

3. 消息队列和缓存

在网络不稳定或连接断开的情况下,可能会导致消息丢失。为了解决这个问题,可以使用消息队列和缓存机制来保证消息的可靠传输和持久化存储。

在 Vuex 中,可以使用数组来作为消息队列,并在连接恢复后重新发送未发送的消息。

const state = {
  socket: null,
  messageQueue: [],
};

const actions = {
  sendMessage({ state }, message) {
    if (state.socket.value.readyState === WebSocket.OPEN) {
      state.socket.value.send(message);
    } else {
      state.messageQueue.push(message);
    }
  },
  reconnect({ state, dispatch }) {
    if (state.socket.value.readyState === WebSocket.CLOSED) {
      dispatch('connect');
      state.messageQueue.forEach((message) => {
        dispatch('sendMessage', message);
      });
      state.messageQueue = [];
    }
  },
};

使用 messageQueue 数组来存储未发送的消息。在发送消息时,如果 WebSocket 连接处于打开状态,直接发送消息;否则,将消息添加到消息队列中。在重新连接时,遍历消息队列并重新发送未发送的消息。

4. 心跳检测

在 WebSocket 连接中,由于网络波动或其他原因,连接可能会在一段时间内变得不活跃。为了保持连接的稳定性,可以使用心跳检测机制来定期发送心跳消息,以确保连接保持活跃。

const PING_INTERVAL = 5000; // 心跳间隔,单位为毫秒

const actions = {
  connect({ commit, dispatch }) {
    const socket = useWebSocket('wss://example.com/socket');

    socket.value.onopen = () => {
      console.log('WebSocket connected');

      // 启动心跳检测
      setInterval(() => {
        dispatch('sendHeartbeat');
      }, PING_INTERVAL);
    };

    // ...
  },
  sendHeartbeat({ state }) {
    if (state.socket.value.readyState === WebSocket.OPEN) {
      state.socket.value.send('ping');
    }
  },
};

在上面的例子中,在连接建立后启动了一个定时器,定期发送心跳消息("ping")。通过定期发送心跳消息,可以确保连接保持活跃,并在一段时间内检测到连接断开的情况。

5. 错误处理

在使用 WebSocket 过程中,可能会出现各种错误,如连接错误、消息发送失败等。为了处理这些错误,可以在相应的事件处理程序中进行错误处理。

socket.value.onerror = (error) => {
  console.error('WebSocket error:', error);
};

socket.value.onmessage = (event) => {
  // 处理接收到的消息
};

socket.value.onclose = (event) => {
  if (event.code === 1006) {
    console.error('WebSocket connection closed unexpectedly');
  } else {
    console.log('WebSocket disconnected');
  }
};

onerror 事件处理程序中打印错误信息,并在 onclose 事件处理程序中根据关闭代码进行适当的错误处理。

6. 清理和销毁

在 Vue 3 中,组件销毁时,需要确保关闭 WebSocket 连接以及清理相关资源,以避免内存泄漏和不必要的网络连接。

import { onBeforeUnmount } from 'vue';

export default {
  setup() {
    const socket = useWebSocket('wss://example.com/socket');

    // ...

    onBeforeUnmount(() => {
      if (socket.value && socket.value.readyState === WebSocket.OPEN) {
        socket.value.close();
      }
    });

    // ...
  },
};

使用 onBeforeUnmount 钩子函数来监听组件销毁前的事件,并在该事件触发时关闭 WebSocket 连接。


收藏



扫描二维码,在手机上阅读

    评论一下?

    OωO
    取消
      1. 头像
        路人甲
        沙发
        文章不错
        回复