websocket结合promise的通信协议

1.前言

为什么会将websocket和promise所联系起来呢?

因为websocket不像http请求一样,发送的请求不会得到对应的回复,这样就会导致如果通过websocket发送消息之后,就无法对此消息进行追溯,使用起来非常不方便,并且很多功能无法实现,与客户端/服务端协调好数据个时候,就可以通过promise获取到消息的回执结果了

如何结合起来?

大致就是websocket的两端(客户端,服务端),提前确定好websocket消息的格式,进行协调,需要注意有个关键点,就是每个消息都会有一个唯一标识(uuid),发送到服务端的消息的状态以及promise的成功与失败,都需要根据这个唯一标识进行处理

2.步骤拆分

  1. 首先创建一个自定义的websocket的消息发送的方法
js 复制代码
const send = (param) => {}
  1. 在每个发送到服务端消息中都添加一个uuid,用于标识当前消息
js 复制代码
const send = (param) => {
    const data = {
        uuid:... // uuid
        ...param
    }
}
  1. 发送消息的方法返回一个promise,得到promise的resolve与reject方法
js 复制代码
const send = (param) => {
  return new Promise((resolve,reject)=>{
    const data = {
        uuid:... // uuid
        ...param
    }
   })
}
  1. 创建一个空对象,对象中保存promise的resolve与reject方法(这里可以自定义websocket消息超时的处理逻辑,可自行拓展)
js 复制代码
const send = (param) => {
  return new Promise((resolve,reject)=>{
    const data = {
        uuid:... // uuid
        ...param
    }
    const promiseData = {resolve,reject}
   })
}
  1. 将此对象添加到一个Map解构,其中的key就是唯一标识,value就是上方创建的对象,这样的话,每个消息都会有一个单独的对象,可以控制此消息的成功,失败,超时等等处理
js 复制代码
const receiverMap = new Map()
const send = (param) => {
  return new Promise((resolve,reject)=>{
    const data = {
        uuid:... // uuid
        ...param
    }
    const promiseData = {resolve,reject}
    receiverMap.set(data.uuid, promiseData)
   })
}
  1. 然后将websocket消息发送出去(需要保证在这些操作之前websocket已经连接了)
js 复制代码
const receiverMap = new Map()
const send = (param) => {
  return new Promise((resolve,reject)=>{
    const data = {
        uuid:... // uuid
        ...param
    }
    const promiseData = {resolve,reject}
    receiverMap.set(data.uuid, promiseData)
    webscoket.send(data)
   })
}
  1. 服务端接收到客户端发送的websocket消息之后,将唯一标识(uuid)提取出来,然后执行对应操作
  2. 对应操作执行成功或失败后按照与客户端协定好的格式返回给客户端,例如定义一个status字段,0表示成功,1表示执行失败,需要注意,这里的uuid也需要返回给客户端,客户端需要获取消息对应的请求是什么
  3. 客户端接收到请求后,将status,uuid字段解构出来,此时就可以通过uuid从Map解构中获取到对应的promise的resolve与reject方法了,此时再根据status的状态决定调用resolve还是reject即可
js 复制代码
 webscoket.addEventListener('message', (data)=>{
   // 解析messageData的内容
  const { uuid, status,param } = data
  // 获取当前接受到的消息所对应的websocket消息对象
  const msgRectiver = receiverMap.get(uuid)
  
  if(status === 0){
    msgRectiver.resolve(param)
  } else {
    msgRectiver.reject(param)
  }
 })
  1. 注意,请求收到后,无论失败还是成功,都需要将Map解构中当前的uuid删除掉,避免大量数据不清楚导致的Map解构过大
js 复制代码
 webscoket.addEventListener('message', (data)=>{
   // 解析messageData的内容
  const { uuid, status,param } = data
  // 获取当前接受到的消息所对应的websocket消息对象
  const msgRectiver = receiverMap.get(uuid)
  
  if(status === 0){
    msgRectiver.resolve(param)
  } else {
    msgRectiver.reject(param)
  }
  // 从Map中删除对应的消息
  receiverMap.delete(uuid)
 })

3.整体代码

js 复制代码
const receiverMap = new Map()
const send = (param) => {
  return new Promise((resolve,reject)=>{
    const data = {
        uuid:... // uuid
        ...param
    }
    const promiseData = {resolve,reject}
    receiverMap.set(data.uuid, promiseData)
    webscoket.send(data)
   })
}

 webscoket.addEventListener('message', (data)=>{
   // 解析messageData的内容
  const { uuid, status,param } = data
  // 获取当前接受到的消息所对应的websocket消息对象
  const msgRectiver = receiverMap.get(uuid)
  
  if(status === 0){
    msgRectiver.resolve(param)
  } else {
    msgRectiver.reject(param)
  }
  // 从Map中删除对应的消息
  receiverMap.delete(uuid)
 })

4.补充以及总结

这里只是大致实现了websocket与promise结合后的效果,内部可以进行很多其他的自定义操作,例如超时判断,消息警告,消息正在处理中,等等。

可以根据自己的需求进行调整,通过这里的方法,就可以对websocket消息进行追踪了,并且使用体验也比较好,可以直接使用.then,.catch等方法直接监听本次消息是否执行成功,以及获取到执行过程中服务端返回的一些数据!

到这里,本篇文章内容已经全部结束了,如果有什么其他的想法或者好的建议,欢迎大家私信或评论😁

相关推荐
BK贝壳5 小时前
亿级用户签到位图选型复盘:用 bool-hybrid-array 扛冷启动打卡,也把它和 Roaring/Redis 的边界测清楚了
数据结构·python·性能优化·numpy
2601_966949656 小时前
如何根据研究的起止时间截取分钟级行情?Python 实战与 QuantDash 数据处理指南
开发语言·python·pandas·量化交易·1024程序员节·股票数据·quantdash
itmigrate8 小时前
前端项目里,Object.is 并不是 === 的平替
前端
小大宇10 小时前
Vue知识点6-computed计算属性
前端·javascript·vue.js
程序员海军10 小时前
尤雨溪 : Vue 4 已经在规划中了!
前端·javascript·vue.js
2601_9499706910 小时前
HumanizeDuration 跨端三方库仓颉适配全流程
前端·javascript·flutter
在世修行10 小时前
智学文枢:页面切换与跨页数据预填
python·桌面应用·signal·1024程序员节·pyside·跨页跳转·状态预填
2601_9628857211 小时前
如何用 Python 把 K 线重采样成任意周期?
开发语言·python
打工仔折腾 AI11 小时前
在 Ubuntu ARM64 部署 Q1 V3.0 MuJoCo 模型:加载、单步推理与执行器响应解析
linux·运维·人工智能·python·深度学习·ubuntu·性能优化
信誓旦旦的程序猿12 小时前
【Python量化实战宝典 #21】北向资金跟随手册:聪明钱择时信号(Python 可跑)
python·1024程序员节·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口