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等方法直接监听本次消息是否执行成功,以及获取到执行过程中服务端返回的一些数据!

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

相关推荐
yinuo7 小时前
IndexedDB 使用指南
前端
小徐_23337 小时前
2025,AI 编程元年,我用 TRAE 做了这些!
前端·程序员·trae
沛沛老爹7 小时前
Web开发者实战RAG评估:从指标到工程化验证体系
前端·人工智能·llm·agent·rag·评估
清水白石0087 小时前
《深入 Python 上下文管理器:contextlib.contextmanager 与类实现方式的底层差异全景解析》
开发语言·python
程序员佳佳7 小时前
GPT-4时代终结?GPT-5.2与Banana Pro实测数据公开,普通开发者如何接住这泼天富贵
开发语言·python·gpt·chatgpt·重构·api·midjourney
软件技术NINI8 小时前
JavaScript性能优化实战指南
前端·css·学习·html
Blossom.1188 小时前
多模态大模型LoRA微调实战:从零构建企业级图文检索系统
人工智能·python·深度学习·学习·react.js·django·transformer
小钻风33668 小时前
软件测试: 从入门到实践 (接口测试)
软件测试·python
前端小配角8 小时前
React难上手原因找到了,原来是因为坑太多了。。。
前端
是你的小橘呀8 小时前
零基础也能懂!React Hooks实战手册:useState/useEffect上手就会,告别类组件
前端·架构