websocket结合promise的通信协议

1.前言

为什么会将websocketpromise所联系起来呢?

因为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,得到promiseresolvereject方法
js 复制代码
const send = (param) => {
  return new Promise((resolve,reject)=>{
    const data = {
        uuid:... // uuid
        ...param
    }
   })
}
  1. 创建一个空对象,对象中保存promiseresolvereject方法(这里可以自定义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字段解构出来,此时就可以通过uuidMap解构中获取到对应的promiseresolvereject方法了,此时再根据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.补充以及总结

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

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

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

相关推荐
GoFly开发者3 分钟前
GoFly企业版框架升级2.6.6版本说明(框架在2025-05-06发布了)
前端·javascript·vue.js
qq_3927944811 分钟前
前端缓存踩坑指南:如何优雅地解决浏览器缓存问题?
前端·缓存
朝阳58118 分钟前
在一台服务器上通过 Nginx 配置实现不同子域名访问静态文件和后端服务
服务器·前端·nginx
waterHBO19 分钟前
python 上海新闻爬虫
开发语言·爬虫·python
水银嘻嘻36 分钟前
web 自动化之 Selenium 元素定位和浏览器操作
前端·selenium·自动化
Java开发追求者42 分钟前
base64与图片的转换和预览(高阶玩法)
javascript·html·base64与图片的转换和预览·高阶玩法
GanGuaGua1 小时前
CSS:元素显示模式与背景
前端·javascript·css·html
一个会的不多的人1 小时前
C# NX二次开发:判断两个体是否干涉和获取系统日志的UFUN函数
前端·javascript·html
小离a_a1 小时前
uniapp tabBar 中设置“custom“: true 在H5和app中无效解决办法
前端·uni-app
豆约翰1 小时前
pygame联网飞机大战游戏实现
python·游戏·pygame