前置知识
什么是WebSocket?
WebSocket是一种在单个TCP连接上进行全双工通信的协议。与HTTP相比,WebSocket在建立连接后,客户端和服务器可以自由地、实时地发送数据,无需每次通信都发起新的请求。
WebSocket的工作原理
- 握手建立连接:WebSocket通信始于一个HTTP请求,这个请求包含了一些特殊的头部字段,比如
Upgrade: websocket
,用来告诉服务器希望升级为WebSocket连接。服务器同意后,连接就正式升级为WebSocket连接。 - 数据帧传输:一旦连接建立,后续的数据交换不再遵循HTTP协议,而是使用专门的帧格式进行传输。每个数据帧包含数据的类型、长度以及实际的数据负载,这种机制允许高效且低延迟的数据传输。
- 心跳维护:为了保持连接活跃,WebSocket连接会定期发送心跳帧,即使在没有实际数据传输时也能检测网络状态,及时发现并处理连接中断。
在项目中使用WebSocket
步骤1:创建WebSocket实例
首先,需要创建一个WebSocket对象,指定要连接的服务器地址:
const socket = new WebSocket('ws://your-server-url');
步骤2:监听事件
WebSocket对象有几个重要的事件需要监听:
- open:连接建立时触发。
- message:接收到服务器消息时触发。
- error:发生错误时触发。
- close:连接关闭时触发。
socket.addEventListener('open', (event) => {
console.log('连接已建立');
socket.send('Hello, Server!');
});
socket.addEventListener('message', (event) => {
console.log('收到服务器消息:', event.data);
});
socket.addEventListener('error', (error) => {
console.error('发生错误:', error);
});
socket.addEventListener('close', () => {
console.log('连接已关闭');
});
步骤3:发送消息
通过send
方法可以向服务器发送数据:
socket.send(JSON.stringify({ action: 'sendMessage', data: 'Hello WebSocket!' }));
FIFO队列
先进先出(First In First Out, FIFO)队列遵循最朴素的公平原则:最先到达的元素也最先离开。想象一下银行排队的场景,最早排队的顾客将被优先服务,后来者依次等待。在程序设计中,FIFO队列通过维护一个有序的元素列表,确保元素按照进入队列的顺序被依次处理或移除。
核心操作
FIFO队列的核心操作包括:
- 入队(Enqueue):将新元素添加到队列的末尾。
- 出队(Dequeue):从队列的前端移除元素,并返回该元素。
- 查看队首(Peek/Front):不改变队列,仅查看队列前端的元素。
- 判断队列是否为空(IsEmpty):检查队列中是否有元素。
因为js并没有内置队列这一数据结构,我们可以自己去实现一个简单的带长度的FIFO队列,
export class Queue {
constructor(maxLength) {
this.maxLength = maxLength
this.queue = []
}
// 入队
enqueue(item) {
if (this.queue.length >= this.maxLength) {
this.dequeue() // 如果队列已满,则先移除队首元素
}
this.queue.push(item) // 将新元素添加到队尾
}
// 出队
dequeue() {
if (this.queue.length > 0) {
return this.queue.shift() // 移除并返回队首元素
}
return null // 如果队列为空,则返回 null
}
// 查看队首元素
peek() {
if (this.queue.length > 0) {
return this.queue[0] // 返回队首元素,但不移除
}
return null // 如果队列为空,则返回 null
}
// 获取队列长度
size() {
return this.queue.length
}
// 清空队列
clear() {
this.queue = []
}
}
为了方便,这里我们直接使用VueUse库里面的useWebSocket,可以开箱即用,让我们更专注于业务开发。这里直接上示例代码
import { useWebSocket } from '@vueuse/core'
const groData= ref(new Queue (10))
const { status, data, send, open, close } = useWebSocket('ws://your-server-url', {
autoReconnect: {
retries: 3,
delay: 5000,
onFailed() {
alert('重试 3 次后无法连接 WebSocket')
},
},
// 连接时
onConnected: () => {
send(JSON.stringify({ msg:'向服务器发送消息' }))
},
// 断开连接时
onDisconnected: () => {
send(JSON.stringify({ msg: '告诉服务器关闭连接' }))
},
// 这里接收每一次服务器推送过来的信息
onMessage: (event, e) => {
const temp = JSON.parse(e.data) // 服务器推送过来的数据
groData.value.enqueue(temp) // 入队
}
可以即时获取到服务器推送的数据后,我们就可以将数据推进我们的队列中,然后通过echart进行更新,就可以实现类似心电图的实时波形图了。