首页/开发项目用到了 websocket/
开发项目用到了 websocket
2023-05-05 10:06:03 前端 1292

首次遇见了需要使用到了全双工通信的开发需求,以下是关于 websocket 在我的实际项目中的配置代码。

项目需求

我司是一家医疗机构,所以遇到了顾客上门分诊的需求,顾客在前台扫码进行填写相关信息后,会同步显示在前台的客户端中,根据新客或者老客的标签来给他进行顾问的选择等。由于需要同步显示,需要服务器主动发送数据到客户端,客户端被动接收。
没有 websocket 之前,会通过定时刷新或者通过前端做假进度来实现,但是前者多余的请求相应会带来更多的资源消耗;后者可能会导致信息传递不及时。

使用技术架构

react antd sockJS stompjs 使用 React + ant design + sockJS + stompJS

具体配置如下:

// 引入使用SockJS
import SockJS from "sockjs-client";
import Stomp from "stompjs";
import { Message } from "stompjs";
import moment from 'dayjs'

// 请求地址
const baseUrl = "你自己的 websocket 请求代码";

// 请求头
// const header = {};

// stomp客户端
export let stompClient: Stomp.Client;

// 连接状态
let connetStatus = false;
/**
 * 初始化连接
 */
export const initSocket = (data?: any, setData?: any) => {
  if (!connetStatus) {
    con(data, setData);
  }

  setInterval(() => {
    // 根据连接状态
    if (connetStatus) {
      try {
        // 发送请求

      } catch (error) {
        con(data, setData);
      }
    }
  }, 5000);
};
/**
 * 连接
 */
export const con = (data?: any, setData?: any) => {
  let socket: WebSocket = new SockJS(baseUrl);
  stompClient = Stomp.over(socket);
  stompClient.heartbeat.incoming = 0;
  stompClient.heartbeat.outgoing = 5000;

  let header = {};

  stompClient.connect(
    header,
    () => {
      let today = moment().format('YYYY-MM-DD')
      let yesterday = moment().subtract(1, 'day').format('YYYY-MM-DD')
      connetStatus = true;
      // 设置订阅
      if (today !== yesterday) {
        stompClient.subscribe(
          "/topic/all",
          async (res: Message) => {
            if (res.body) {
              let customerList: any = localStorage?.getItem('customerList')
              await setData([
                JSON.parse(res.body),
                ...JSON.parse(customerList ? customerList : '[]'),
              ]);
              speechInfo().start('你有新的顾客来了')
            }
          },
          // header(sub-id)
          { id: 'customer-subid' }
        );
      }

    },
    (err: any) => {
      console.log("error", err);
    }
  );
};

/**
 * 断开
 */
export const close = () => {
  if (stompClient) {
    stompClient.disconnect(() => {
      stompClient.unsubscribe('customer-subid')
      console.log("websocket 连接断开!");
      connetStatus = false;
    });
  }
};

// 语音播报
const speechInfo = () => {
  let speechInstance = new SpeechSynthesisUtterance();

  return {
    // 语音播报开始
    start: function (content: string) {
      let lang = 'zh-CN'; // zh-HK zh-CN zh-TW
      let text = content;
      if (text !== '') {
        speechInstance.text = text;
        speechInstance.lang = lang;
        speechInstance.volume = 1;
        speechInstance.rate = .9;
        speechSynthesis.speak(speechInstance);
        speechInstance.onend = function (event) {
          console.log("语音播报完毕");
        }
      }
    },

    // 暂停
    pause: function () {
      speechSynthesis.pause();
    },
    // 重新开始
    resume: function () {
      speechSynthesis.resume();
    },
    // 取消
    cancel: function () {
      speechSynthesis.cancel();
    }
  }
};

当有顾客上门扫码后,会主动语音播报前台服务人员,以此去为顾客进行分诊管理。语音播报用了 speechSynthesis 这个 api,语音合成接口,但是在 Chrome 浏览器中,需要用户有交互行为,才能自动播放,正在想办法解决此问题。

这是我第一次接触 websocket,后端同事也是首次接触,不过通过现在的测试,看起来效果还不错,等到正式接口下来后,希望 bug 不要太过离谱,哈哈哈

我来更新了,这几天新增了分诊抽屉组件,通过表单为顾客分诊,进行后续顾问带去面诊的操作,头部增加新建预约等,搜索功能等待接口中,详情页组件拆分 header 搜索组件用了模糊查询,点击跳转到对应的详情页中,开发了长时间未操作退出等,等待后端接口 ing

等待后续更新!!!

一个不断学习的前端小菜鸟
永远不要放弃你那颗追梦之心 up up~