因业务需要,做大屏页面某一处需要不断推送消息,采用websocket技术;

1. 新建socket.ts

在utils文件夹下新建socket.ts;

export default class Socket {
  // cb: 存储回调函数
  constructor(url: string, cb: (data: any) => void) {
    this.url = url;
    this.cb = cb;
    this.connect();
  }

  private readonly url: string = '';
  private cb?: (data: any) => void;
  // 和服务端连接的socket对象
  private ws?: WebSocket;
  private remainPayload: any[] = [];

  public connect() {
    return new Promise<void>(resolve => {
      const ws = new WebSocket(this.url);

      ws.onopen = e => {
        console.info('ws open 连接成功', e);
        this.remainPayload.forEach(payload => {
          ws.send(payload);
        });
        resolve();
      };

      // 得到服务端发送过来的数据
      ws.onmessage = e => {
        if (this.cb) {
          this.cb(e.data);
        }
      };

      ws.onerror = e => {
        console.error('ws error', e);
      };

      // ws.onclose = e => {
      //   console.info('ws close', e);
      // };
      this.ws = ws;
    });
  }

  public async send(payload: any) {
    if (!payload || !this.ws) {
      if (!this.ws) {
        this.remainPayload.push(JSON.stringify(payload));
      }
      return;
    }
    if (this.isConnected) {
      this.ws.send(JSON.stringify(payload));
    } else {
      // 后端主动断开 前端发起请求 需要在连接一次
      await this.connect();
      this.ws.send(JSON.stringify(payload));
    }
  }

  private get isConnected() {
    return this.ws && this.ws.readyState === WebSocket.OPEN;
  }

  public close() {
    if (this.ws) {
      this.ws.close();
      this.ws = undefined;
    }
  }
}

2. 新建websocket.ts

因为我使用pinia统一管理了一下 ,如果 不需要可以跳过这个步骤

import { defineStore } from 'pinia';
import Socket from '@/utils/socket';

const path = `ws://${window.location.host}${window.location.pathname}`;

interface WebSocketModel {
  message: string;
  exhibitWs: Socket | null;
}

export const useWebsocketStore = defineStore('websocket', {
  state: (): WebSocketModel => ({
    message: '',
    exhibitWs: null
  }),
  getters: {},
  actions: {
    initExhibitSocket() {
      const resp = new Socket(`${path}api/ws`, message => {
        this.message = JSON.parse(message);
      });
      this.exhibitWs = resp;
    }
  }
});

3. 定义api/ws的端口

在vite.confing.ts中

'/api/ws': {
        target: 'ws://192.168.2.68:8776',
        ws: false,
        changeOrigin: true
      }

4. 连接

我是在路由守卫中就连接使用 在route/index.ts中

router.beforeEach(to => {
  // 解决持久化失效问题
  const { websocket } = useStore();
  // 建立链接
  if (!websocket.exhibitWs) {
    websocket.initExhibitSocket();
  }
 。。。。
});
Logo

前往低代码交流专区

更多推荐