在vue3中封装使用WebSocket

这篇具有很好参考价值的文章主要介绍了在vue3中封装使用WebSocket。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上篇文章记录了如何在日常开发过程中引入并使用websocket连接,但是在后续的开发过程中发现之前的写法有点问题,比如说多次引用连接会共用一个心跳,如果一个连接关掉了,后续其他的连接可能被一起关掉等等的bug。

所以在这篇文章里针对上篇文章提供的方法进行改进,同时提供兼容vue3写法。

一、创建 WebSocket 类

class Socket {
    constructor(url, opts = {}) {
        this.url = url;
        this.ws = null;
        this.opts = {
            heartbeatInterval: 30000, // 默认30秒
            reconnectInterval: 5000, // 默认5秒
            maxReconnectAttempts: 5, // 默认尝试重连5次
            ...opts
        };
        this.reconnectAttempts = 0;
        this.listeners = {};

        this.init();
    }

    init() {
        this.ws = new WebSocket(this.url);

        this.ws.onopen = this.onOpen.bind(this);
        this.ws.onmessage = this.onMessage.bind(this);
        this.ws.onerror = this.onError.bind(this);
        this.ws.onclose = this.onClose.bind(this);
    }

    onOpen(event) {
        console.log('WebSocket opened:', event);
        this.reconnectAttempts = 0; // 重置重连次数
        this.startHeartbeat();
        this.emit('open', event);
    }

    onMessage(event) {
        console.log('WebSocket message received:', event.data);
        this.emit('message', event.data);
    }

    onError(event) {
        console.error('WebSocket error:', event);
        this.emit('error', event);
    }

    onClose(event) {
        console.log('WebSocket closed:', event);
        this.stopHeartbeat();
        this.emit('close', event);
        if (this.reconnectAttempts < this.opts.maxReconnectAttempts) {
            setTimeout(() => {
                this.reconnectAttempts++;
                this.init();
            }, this.opts.reconnectInterval);
        }
    }

    // 发送心跳
    startHeartbeat() {
        this.heartbeatInterval = setInterval(() => {
            if (this.ws.readyState === WebSocket.OPEN) {
                this.ws.send('ping'); // 可以修改为你的心跳消息格式
            }
        }, this.opts.heartbeatInterval);
    }

    // 停止心跳
    stopHeartbeat() {
        if (this.heartbeatInterval) {
            clearInterval(this.heartbeatInterval);
            this.heartbeatInterval = null;
        }
    }

    send(data) {
        if (this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(data);
        } else {
            console.error('WebSocket is not open. Cannot send:', data);
        }
    }

    on(event, callback) {
        if (!this.listeners[event]) {
            this.listeners[event] = [];
        }
        this.listeners[event].push(callback);
    }

    off(event, callback) {
        if (!this.listeners[event]) return;
        const index = this.listeners[event].indexOf(callback);
        if (index !== -1) {
            this.listeners[event].splice(index, 1);
        }
    }

    emit(event, data) {
        if (this.listeners[event]) {
            this.listeners[event].forEach(callback => callback(data));
        }
    }
}

export default Socket;

我们首先定义一个 Socket 类,该类会负责与 WebSocket 服务器建立连接、发送和接收数据、以及管理心跳和重连逻辑。 

在你的Vue组件中使用这个类时,可以这样注册事件:

import Socket from './socket.js';

export default {
    data() {
        return {
            socket: null
        };
    },
    created() {
        this.socket = new Socket('ws://your-websocket-url');
        this.socket.on('open', event => {
            console.log("Connected to server", event);
        });
        this.socket.on('message', data => {
            console.log("Received data:", data);
        });
        this.socket.on('error', error => {
            console.error("WebSocket Error:", error);
        });
        this.socket.on('close', event => {
            console.log("Connection closed", event);
        });
    },
    beforeDestroy() {
        // 取消所有事件监听器
        this.socket.off('open');
        this.socket.off('message');
        this.socket.off('error');
        this.socket.off('close');
    },
    methods: {
        sendToServer(data) {
            this.socket.send(data);
        }
    }
}

二、使用 Vue 3 的 Composition API

为了在 Vue 3 中更好地使用上述的 Socket 类,我们将其封装为一个 composable 函数,这样可以轻松地在任何 Vue 组件中使用 WebSocket。

import { ref, onUnmounted } from 'vue';

interface SocketOptions {
  heartbeatInterval?: number;
  reconnectInterval?: number;
  maxReconnectAttempts?: number;
}

class Socket {
  url: string;
  ws: WebSocket | null = null;
  opts: SocketOptions;
  reconnectAttempts: number = 0;
  listeners: { [key: string]: Function[] } = {};
  heartbeatInterval: number | null = null;

  constructor(url: string, opts: SocketOptions = {}) {
    this.url = url;
    this.opts = {
      heartbeatInterval: 30000,
      reconnectInterval: 5000,
      maxReconnectAttempts: 5,
      ...opts
    };

    this.init();
  }

  init() {
    this.ws = new WebSocket(this.url);

    this.ws.onopen = this.onOpen.bind(this);
    this.ws.onmessage = this.onMessage.bind(this);
    this.ws.onerror = this.onError.bind(this);
    this.ws.onclose = this.onClose.bind(this);
  }

  onOpen(event: Event) {
    console.log('WebSocket opened:', event);
    this.reconnectAttempts = 0;
    this.startHeartbeat();
    this.emit('open', event);
  }

  onMessage(event: MessageEvent) {
    console.log('WebSocket message received:', event.data);
    this.emit('message', event.data);
  }

  onError(event: Event) {
    console.error('WebSocket error:', event);
    this.emit('error', event);
  }

  onClose(event: CloseEvent) {
    console.log('WebSocket closed:', event);
    this.stopHeartbeat();
    this.emit('close', event);
    
    if (this.reconnectAttempts < this.opts.maxReconnectAttempts!) {
      setTimeout(() => {
        this.reconnectAttempts++;
        this.init();
      }, this.opts.reconnectInterval);
    }
  }

  startHeartbeat() {
    if (!this.opts.heartbeatInterval) return;
    
    this.heartbeatInterval = window.setInterval(() => {
      if (this.ws?.readyState === WebSocket.OPEN) {
        this.ws.send('ping');
      }
    }, this.opts.heartbeatInterval);
  }

  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }
  }

  send(data: string) {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(data);
    } else {
      console.error('WebSocket is not open. Cannot send:', data);
    }
  }

  on(event: string, callback: Function) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
  }

  off(event: string) {
    if (this.listeners[event]) {
      delete this.listeners[event];
    }
  }

  emit(event: string, data: any) {
    this.listeners[event]?.forEach(callback => callback(data));
  }
}

export function useSocket(url: string, opts?: SocketOptions) {
  const socket = new Socket(url, opts);

  onUnmounted(() => {
    socket.off('open');
    socket.off('message');
    socket.off('error');
    socket.off('close');
  });

  return {
    socket,
    send: socket.send.bind(socket),
    on: socket.on.bind(socket),
    off: socket.off.bind(socket)
  };
}

在组件中使用:

import { defineComponent } from 'vue';
import { useSocket } from './useSocket';

export default defineComponent({
  name: 'YourComponent',
  setup() {
    const { socket, send, on, off } = useSocket('ws://your-websocket-url');

    on('open', event => {
      console.log("Connected to server", event);
    });
    on('message', data => {
      console.log("Received data:", data);
    });
    on('error', error => {
      console.error("WebSocket Error:", error);
    });
    on('close', event => {
      console.log("Connection closed", event);
    });

    return {
      send
    };
  }
});

三、总结

以上是具体实现方案,在后续开发过程中如果有更好的写法,也会更新本文。文章来源地址https://www.toymoban.com/news/detail-731453.html

到了这里,关于在vue3中封装使用WebSocket的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ai问答:vue3+pinia+WebSocket 封装断线重连(实战)

    把 Socket 实例 挂载到全局 为方便梳理,请忽略 typescript ,一切尽在注释中 Socket封装(断线重连) 这个 WebSocket 类封装了 WebSocket 的连接、重连、发送数据等方法。 在 connect 方法中,它会连接 WebSocket ,并绑定相关事件监听。 在 onclose 事件中,它会调用 reconnect 方法进行重连。 recon

    2024年02月03日
    浏览(53)
  • Vue3+Axios网络请求封装

    本文将详细介绍一款基于Axios+Typescript封装的网络请求库,该库可以自动携带token、拦截请求和响应等操作,并能够处理请求重复、超时和错误状态码等异常情况。 Axios 是基于Node.js的HTTP客户端,也是一款广泛使用的网络请求库。它具有使用简单、可扩展性高、易用性好等特点

    2024年02月07日
    浏览(44)
  • vue封装和使用websocket

    最近做了一个数据大屏的项目,使用了websocket来实现数据实时更新的需求,简单记录分享一下。 1、WebSocket协议是基于TCP的一种新的网络协议,允许服务端主动向客户端推送数据,实现全双工通信。 2、在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可

    2024年02月06日
    浏览(37)
  • vue3中使用websocket

    效果图 实现 src/util/socket.ts src/store/webSocket.ts 这里面放到了登录成功后在连接websocket src/viwes/login.vue 附赠后台建议websocket服务供测试使用 链接:https://pan.baidu.com/s/1RzbWiooLwCIuDTnEfN_x0Q?pwd=p58w 提取码:p58w

    2024年02月11日
    浏览(35)
  • vue3使用websocket(亲测解决)

    1.需要后端给你一个ws的接口比如: 我这里的name是后端要求登录成功后搞得 2.后端给我个登录的接口,需要登录后才能实现长链接 3.封装init方法 网上找了一堆没用的方法,不建议看 所有代码合集

    2024年02月14日
    浏览(81)
  • 使用vue3简单实现WebSocket通信

    关于WebSocket通信的简单介绍: 握手阶段:在建立WebSocket连接之前,客户端需要发送一个HTTP请求到服务器,请求升级为WebSocket协议。这个过程称为握手(Handshake)。如果服务器支持WebSocket协议,它将返回带有特定标头的HTTP响应,表示握手成功。 建立连接:客户端收到服务器的

    2024年02月16日
    浏览(36)
  • vue3.2+vite+代理,使用websocket

    之前以为websocket复杂,想使用插件来实现,查了一番资料,原生写法就很简单。 查询列表,需要实时获取员工上报的数据 Table.vue 因为跨域问题,这里使用了vite的proxy代理功能 vite.config.ts 如果代理设置好,连接成功,以上websocket会打印\\\"连接成功\\\"和输出返回。 完! 项目运行

    2024年02月10日
    浏览(47)
  • Vue3 Hooks函数使用及封装思想

    目录 一. 什么是hooks函数? 二、如何封装一个hooks函数 三、Hooks 常用 Demo (1)验证码倒计时 (2)防抖 (3)节流 专业解释:Vue 3中的Hooks函数是一种用于在组件中共享可复用逻辑的方式。 大白话:将单独功能的js代码抽离出来, 加工成公共函数,从而达到逻辑复用。 在尤大

    2024年02月11日
    浏览(32)
  • vue3【使用axios并封装axios请求】

    第一步:安装axios 第二步:编写请求文件 新建request.js 简单的axios封装,里面相关提示信息,自己可以引入element-plus去添加

    2024年02月04日
    浏览(59)
  • vue3项目使用WebSocket 传输 Protobuf 格式的数据

    前端和后端数据传输常用数据格式: JSON(JavaScript Object Notation):与 HTTP 协议和 REST API 配合使用时,JSON 数据是最常用的数据格式之一。对于 WebSocket,JSON 数据同样适用。客户端可以将消息转换为 JSON 对象,并将其发送到服务器进行处理,在服务器上生成响应并返回给客户端

    2024年02月10日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包