前端微服务 websocket的简易封装,以及iframe如

一、功能解读

  • 主应用封装 ws, 子应用共享;
  • 心跳检测、自动重连;
  • iframe子应用 订阅、推送(onPubSocket 、onSubSocket);

二、代码片段

类型自行忽略


import _ from 'lodash'
import store from '../store'
// import { Notice } from 'view-design'
import Notification from '../components/Notification'
import { Callback, eventsMessageItem, wsOptions, resultType } from '../model/websocket'

class Websocket {

  private websocket: any // ws 实体
  private timer: any // 心跳检测定时器
  private socketUrl: string // ws url
  private timeout: number // 心跳检测时间间隔
  private serverPort: number // ws 端口号
  private isConnect: boolean = false // ws 是否连接
  private eventsQueue: Record<string, Callback[]> = {} // pud sub 消息订阅推送队列
  public eventsMessage: eventsMessageItem[] = [] // 保存的消息 只保存最新的20条

  constructor (wsOpt: wsOptions) {
    const { socketUrl, serverPort, timeout } = wsOpt
    this.socketUrl = socketUrl
    if (serverPort) this.serverPort = serverPort
    if (timeout) this.timeout = timeout
  }

  private createWebSocket = () => {
    if( typeof WebSocket === 'undefined' ) return console.error("您的浏览器不支持Websocket通信协议!")
    if (this.websocket) return
    this.initWebSocket()
  }
  // 初始化websocket
  public initWebSocket = () => {
    // noticeOpen()
    this.websocket = new WebSocket(this.socketUrl)
    // 连接成功
    this.websocket.onopen = (e) => {
      this.isConnect = true
      this.openStatus(e)
    }
    // 连接关闭
     this.websocket.onclose = (e) => {
      this.closeStatus(e)
    }
    // 接收信息
    this.websocket.onmessage = (e) => {
      this.onmessage(e)
    }
    // 连接发生错误的回调方法
    this.websocket.onerror = (e) => {
      console.log(`ws 连接错误:${e}`)
    }
  }

  // 重连
  private reconnect = () => {
    let cTimer: any = null
    cTimer && clearTimeout(cTimer)
    cTimer = setTimeout(() => {
      this.initWebSocket()
    }, 5000)
  }

  // 心跳检测
  private socketHeartbeat = () => {
    if (!this.isConnect) return
    this.timer && clearTimeout(this.timer)
    this.timer = setTimeout(() => {
      if (this.websocket.readyState === 1) {  // 连接正常 发送心跳包
        console.log(`ws: 开启心跳检测 --- 发送心跳包`)
        this.websocket.send(JSON.stringify({
          type: 'heartbeat',
          msg: 'heartbeat message'
        }));
      } else {  // 否则重连
        this.isConnect = false
        this.reconnect();
      }
    }, this.timeout)
  }

  // 重置心跳
  private onReset = () => {
    console.log(`ws: 重置心跳`)
    clearTimeout(this.timer)
    // 重启心跳
    this.socketHeartbeat()
  }

  // 数据接收
  private onmessage = (e) => {
    _.debounce(() => this.socketHeartbeat(), 2000)()
    this.handleMessage(e)
  }

  // 消息处理
  private handleMessage = (e) => {
    const res = JSON.parse(e.data)
    const { type, data } = res

    switch (type) {
      case 'heartbeat': // 心跳
        console.info(`ws: 心跳正常`)
        break;
      case 'resource': // 资源数据
        setDashboard(data)
        break;
      case 'new-message': // 消息通知
        store.commit(`Launcher/updateNemMsg`, data)
        break;
      case 'task-total': // 任务
        store.commit(`Launcher/updateIsTask`, data)
        break;
      case 'app-update-total': // 应用数据
        this.onSubSocket('app-update-total', 'ws: message')
        break;
      default: // 其他通知
        const length = this.eventsMessage.length
        if (length >= 20) {
          this.eventsMessage.shift()
          this.eventsMessage.push(res)
        }
        // this.onSubSocket('notify', 'ws: message')
    }
  }

  // 发布
  public onPubSocket = (eventName: string, cb: Callback) => {
    const query: Callback[] = this.eventsQueue[eventName] || [] // 获取原队列
    query.push(cb)  // 队列中追加cb
    this.eventsQueue[eventName] = query // 重新赋值事件队列
  }

  // 订阅
  public onSubSocket = (eventName: string, ...args: any[]) => {
    const query: Callback[] = this.eventsQueue[eventName] || [] //  获取事件队列
    if (query.length < 1) return 
    query.forEach((t: Callback) => { t(...args) }) // 执行事件队列中的回调函数数组
  }

  // 打开状态
  private openStatus = (e) => {
    console.log(`ws 连接成功:${e}`)
  }

  // 数据发送
  public websocketSend = (data) => {
    this.websocket.send(data)
  }

  // 关闭状态
  private closeStatus = (e) => {
    console.log(`ws 连接关闭:${e}`)
  }

  // 关闭
  public onClose = () => {
    this.isConnect = false
    clearTimeout(this.timer)
    this.timer = null
    this.websocket.close()
  }
}

const setDashboard = (data: resultType) => {
  switch (data.name) {
    case 'memory': // 内存 使用率
      store.commit(`Launcher/updateDegRam`, data.usage * 1.8)
      break;
    case 'cpu': // cpu 使用率
      store.commit(`Launcher/updateDegCpu`, data.usage * 1.8)
      break;
    case 'network': // 上传下载速率
      store.commit(`Launcher/updateReceive`, data.receive)
      store.commit(`Launcher/updateTransmit`, data.transmit)
      break;
    default:
      break;
  }
}
 
export default new Websocket({
  socketUrl: 'ws://192.168.24.26:9999/ugreen/v1/desktop/ws',
  serverPort: 80,
  timeout: 25000
})


三、示例

3.1 主应用初始化

// ws 相关
initWebSocket () {
    Websocket.initWebSocket()
    Websocket.onPubSocket('state', (data) => {
      console.log(`这是监听到 ws 的消息:${data}`)
    })
    this.$once('hook:beforeDestroy', function () {
      Websocket.onClose()
      window.removeEventListener("message", () => {})
    })
},

3.2 子应用监听看下方使用文档

四、使用文档


#### websocket 使用说明

##### 1. 介绍

- 1.1 ws 的心跳检测时间是 25s, 可自定义

- 1.2 ws 意外断开重连时间是心跳检测时间的基础上 + 5s

- 1.3 launcher 桌面端会实时接收 server 端推送的消息, 并全部记录在 eventsMessage 内

- 1.4 接收消息后会主动调用 onSubSocket 方法通知订阅者

- 1.5 接收者通过 注册 onPubSocket 方法接收

##### 2. 使用

挂在到window: window.customWebsocket = websocket

- 2.1 通知订阅者示例

```js
 Websocket.onSubSocket(msgType, 'ws: message')
```

*   2.1 接收者示例

```js
 Websocket.onPubSocket(msgType, (msg) => {})
```

##### 3. 其他模块使用

*   3.1 当挂在在全局 window 上 属性为 customWebsocket; msgType需一致

```js
// launcher 应用
 Websocket.onSubSocket(msgType, 'ws: message')

// 子应用接收示例
(window.top as any).customWebsocket.onPubSocket(msgType, (msg) => {})

```

*   3.1 当 通过 postMessage 方式接收时

```js
// launcher 应用 msgObj 会包含type 消息类型, 子应用自行过滤
 window.top.postMessage(msgObj, '*')

// 子应用接收示例
(top as any).addEventListener('message', (msgObj) => {})

```
全部评论

相关推荐

起名字真难233:人家只有找猴子的预算,来个齐天大圣他们驾驭不住呀😂😂
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务