大涛子客栈

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 通用代码

整体过程:

  • 发起连接
  • 发送数据(发送心跳等)
  • 接收数据
  • 关闭连接
  • 断线重连
  • 异常处理…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
export default class WebSocketHandle {
/**
* @description: 初始化实例属性,保存参数
* @param {String} url ws的接口
* @param {Function} msgCallback 服务器信息的回调传数据给函数
* @param {String} name 可选值 用于区分ws,用于debugger
*/
constructor(url, msgCallback, name = 'default') {
this.url = url
this.msgCallback = msgCallback
this.name = name
this.ws = null // websocket对象
this.status = null // websocket是否关闭
}
/**
* @description: 初始化 连接websocket或重连webSocket时调用
* @param {*} 可选值 要传的数据
*/
connect(data, callback) {
// 新建 WebSocket 实例
this.ws = new WebSocket(this.url)
this.ws.onopen = e => {
// 连接ws成功回调
this.status = 'open'
if (callback) {
callback()
}

console.log(`${this.name}连接成功`, e)

this.heartCheck()

if (data !== undefined) {
// 有要传的数据,就发给后端
return this.ws.send(data)
}
}
// 监听服务器端返回的信息
this.ws.onmessage = e => {
// 把数据传给回调函数,并执行回调
if (e.data === 'pong') {
this.pingPong = 'pong' // 服务器端返回pong,修改pingPong的状态
}
return this.msgCallback(e.data)
}
// ws关闭回调
this.ws.onclose = e => {
this.closeHandle(e) // 判断是否关闭
}
// ws出错回调
this.onerror = e => {
this.closeHandle(e) // 判断是否关闭
}
}

// 心跳机制
heartCheck() {
this.pingPong = 'ping' // ws的心跳机制状态值
this.pingInterval = setInterval(() => {
if (this.ws.readyState === 1) {
// 检查ws为链接状态 才可发送
this.ws.send('ping') // 客户端发送ping
}
}, 10000)
this.pongInterval = setInterval(() => {
this.pingPong = false
if (this.pingPong === 'ping') {
this.closeHandle('pingPong没有改变为pong') // 没有返回pong 重启webSocket
}
// 重置为ping 若下一次 ping 发送失败 或者pong返回失败(pingPong不会改成pong),将重启
console.log('返回pong')
this.pingPong = 'ping'
}, 20000)
}

// 发送信息给服务器
sendHandle(data) {
console.log(`${this.name}发送消息给服务器:`, data)
return this.ws.send(data)
}

// 因为webSocket并不稳定,规定只能手动关闭(调closeMyself方法),否则就重连
closeHandle(e = 'err') {
if (this.status !== 'close') {
console.log(`${this.name}断开,重连websocket`, e)
if (this.pingInterval !== undefined && this.pongInterval !== undefined) {
// 清除定时器
clearInterval(this.pingInterval)
clearInterval(this.pongInterval)
}
this.connect('') // 重连
} else {
console.log(`${this.name}websocket手动关闭`)
}
}

// 手动关闭WebSocket
closeMyself() {
console.log(`关闭${this.name}`)
this.status = 'close'
return this.ws.close()
}
}

 评论