Hkc

vuePress-theme-reco Hkc    2025
Hkc Hkc

Choose mode

  • dark
  • auto
  • light
TimeLine
GitHub
author-avatar

Hkc

25

Article

13

Tag

TimeLine
GitHub
  • Vue

  • Websocket

    • WebSocket
  • JS

  • CSS

  • Canvas

  • HTTP

  • GIT

  • SERVER

  • MORE

WebSocket

vuePress-theme-reco Hkc    2025

WebSocket

Hkc 2021-04-16 WebSocket

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送. 浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。 当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

# WebSocket 创建

以下 API 用于创建 WebSocket 对象。

var Socket = new WebSocket(url, [protocol])

# WebSocket 属性

Socket.readyState,只读属性 readyState 表示连接状态,可以是以下值:

0 -> 表示连接尚未建立。

1 -> 表示连接已建立,可以进行通信。

2 -> 表示连接正在进行关闭。

3 -> 表示连接已经关闭或者连接不能打开

Socket.bufferedAmount

只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节

# WebSocket 事件

事件 事件处理程序 描述
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发

# WebSocket 方法

以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

Socket.send() //使用连接发送数据

Socket.close() //关闭连接

# 在使用过程中,遇到的问题

订阅时发现 new 完之后直接去 send 会偶发失败的情况(new 需要一个过程), 这种情况通常的处理是订阅函数外加一层延时器 setTimeout,但是 setTimeout 设置的时间决定了容错高低,且并不友好。基于此,

我们在订阅前根据 readyState 判断是否 websocket 连接已建立,手动实现一个 Promise,在订阅方法中去 await readyState 从 0 变 1 的情况


//创建连接
let socket = new websocket(url)

socket.onopen=()=>{
  //此时readyState为1,创建自定义事件socketOpen派发订阅已成功
  window.dispatchEvent(new CustomEvent('socketOpen'))
}

//创建等待函数,等待readyState从0变1
function websocketReady(){
  return new Promise((resolve,reject)=>{
    if(socket.readyState==0){
      //监听自定义函数 这里就是readyState从0变1的情况
      window.addEventListener('socketOpen',()=>{
        window.removeEventListener('socketOpen',()=>{})
        resolve()
      })
    }else if(socket.readyState==1){
      resolve()
    }else{
      //readyState 2或3 表示未建立连接或建立失败
      console.error('websocket连接超时')
      reject()
    }
  })
}

//自定义订阅方法
function async subscribe(topic,param){
  await websocketReady()
  socket.send(param)
  //todo...
}