总结[设计] 如何设计大屏同步方案

大致的需求就是,在客户现场展示几个大屏,而客户可以在管理端控制每个大屏的展示布局。

那么针对这种情况我们应该如何设计呢?

首先我们使用的方案是websocket长连接方案。因为在这个需求总管理端需要知道连接的每个大屏的状态,而客户端需要实时同步大屏数据和上报自身状态同步给客户端。

对此使用长连接通讯相对来讲是比较靠谱的而且很容易实现。

在这里我们虽然展示了不同的大屏,但是每个大屏默认会有一个初始配置,用于首次展示。

那么这种展示方式的连接流程数据交方式是什么?

首先我们的连接流程指的是对接websocket的连接流程,在此我们规定了如下格式

go 复制代码
type DataMessage struct{
  PageId:      string `json:pageId`,      // 页面唯一标识
  PageStatus:  int    `json:pageStatus`   // 页面的类型 1 管理端 | 2 展示端
  PageVersion: int    `json:pageStatus`   // 页面配置版本
  Data:        string `json: data`        // 同步的数据
}

在页面连接之前会自己生成一个md5表示当前的页面ID,这条数据也用于存储该页面对应socket连接的key值,这样设计的关键点是对需要广播的配置页面实现精准控制,保证每个配置的独立性。数据结构如下

go 复制代码
type pageWebsocket struct {
	PageId       string          `json:pageId`        // 唯一标识
   PageStatus:  int             `json:pageStatus`    // 页面的类型 1 管理端 | 2 展示端
   PageVersion: int             `json:pageStatus`    // 页面配置版本
	ws           *websocket.Conn `json:ws`            // 版本号
}
var pageWebsocketMap = map[string] pageWebsocket{}   // 数据map

假设我们有四个展示端页面一个管理端,在一开始进入的时候会产生5条连接,每个连接均通过上述方式记录,此时,管理端会接收到由四个页面同步过来的数据,并展示在管理页面中,每次配置时端可以批量选择需要同步的页面,被选中的页面的pageId就会被作为广播的发送者,通过之前pageWebsocketMap存储的ws连接句柄来广播数据。

展示端如果需要同步自身数据,需要通过PageStatus找到管理端实现管理端的数据广播(我们目前做的是只有一个管理端页面,不存在多管理端控制同一页面)。

每次窗口关闭时释放pageWebsocketMap存储的长连接,而针对释放我们采取的是服务端生成一个唯一标识,该标识仅仅标识本次连接是唯一的,用于defer函数回调时使用

对于客户端使用store来做数据管理,格式如下所示

typescript 复制代码
interface State {
  ws: WebSocket | undefined;
  isConnect: boolean;
  data: any;
}

export default createStore<State>({
  state: {
    ws: undefined,    // ws句柄
    isConnect: false, // 是否连接
    data: {},         // 数据
  },
  getters: {},
  mutations: {
    setData(store, payload: WebSocket) {
      store.data = payload;
    },
    setWs(store, payload: WebSocket) {
      store.ws = payload;
    },
    setState(store, payload: boolean) {
      store.isConnect = payload;
    },
  },
  actions: {
    initWebsocket(store, userId: string) {
      if (
        store.state.ws &&
        store.state.ws.CLOSED !== 3 &&
        store.state.isConnect
      ) {
        store.state.ws.close();
      }
      const ws = new WebSocket(WS_URL);
      store.commit("setWs", ws);
      ws.onopen = () => {
        store.commit("setState", true);
        const params = JSON.stringify({ userId, type: 1 });
        store.commit("setData", params);
      };
      ws.onerror = () => {
        store.commit("setState", false);
      };
      ws.onclose = () => {
        store.commit("setState", false);
      };
      ws.onmessage = (ev: MessageEvent<any>) => {
        store.commit("setData");
        const data = JSON.parse(ev.data);
        console.log(data);
      };
    },
    sendData(store, jsonData: any) {
      if (store.state.ws) {
        store.state.ws.send(JSON.stringify(jsonData));
      }
    },
  },
  modules: {},
});

该函数仅仅起到ws的透传管理,具体的数据发送依靠sendData实现,而响应则是依靠onmessage来作为数据的同步,页面使用computed或直接使用useStore获取数据即可完成页面的动态刷新操作

相关推荐
万叶学编程2 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js
前端李易安4 小时前
Web常见的攻击方式及防御方法
前端
PythonFun4 小时前
Python技巧:如何避免数据输入类型错误
前端·python
知否技术4 小时前
为什么nodejs成为后端开发者的新宠?
前端·后端·node.js
hakesashou4 小时前
python交互式命令时如何清除
java·前端·python
天涯学馆4 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF5 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi5 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi5 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript