一.websocket
什么是websocket?
定义:WebSocket 协议:WebSocket 是一个基于 TCP 的协议,允许在客户端和服务器之间建立一个持久的双向通信通道。它的通信通常基于一个简单的 HTTP 请求来建立连接,然后切换到 WebSocket 协议。
利用websocket实现实时通信的过程
js
<script>
// 创建 WebSocket 连接
const socket = new WebSocket('ws://localhost:8080'); // WebSocket 服务器地址
// 监听 WebSocket 连接成功事件
socket.onopen = () => {
console.log('WebSocket connection established');
displayChatMessage('System', 'Connected to the WebSocket server');
};
// 监听接收到的消息
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received message:', message);
if (message.type === 'chat') {
displayChatMessage(message.user, message.content);
}
};
// 监听 WebSocket 错误事件
socket.onerror = (error) => {
console.error('WebSocket error: ', error);
};
// 监听 WebSocket 关闭事件
socket.onclose = () => {
console.log('WebSocket connection closed');
displayChatMessage('System', 'Disconnected from the WebSocket server');
};
// 显示聊天消息
function displayChatMessage(user, content) {
const chatBox = document.getElementById('chatBox');
const message = document.createElement('p');
message.textContent = `${user}: ${content}`;
chatBox.appendChild(message);
chatBox.scrollTop = chatBox.scrollHeight; // 滚动到最新消息
}
// 发送消息到服务器
document.getElementById('sendButton').onclick = () => {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value;
if (message) {
// 发送消息到服务器
const data = JSON.stringify({ type: 'chat', content: message, user: 'Client1' });
socket.send(data);
// 显示发送的消息
displayChatMessage('You', message);
messageInput.value = ''; // 清空输入框
}
};
</script>
实例方法总结:
- 1.onopen:监听连接建立成功,而后触发的事件
- 2.onmessage:监听收到websocket服务器发送的新请求执行的回调函数
- 3.onerror:监听websocket失败触发的回调函数
- 4.send:向服务器发送请求
- 5.onclose:关闭websocket连接触发的回调函数
二.轮询(polling)和长轮询(long Polling)
1.轮询:客户端定期向服务端发送请求,一般是用例如setInterval每隔一段时间向服务器发送请求,
js
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import axios from 'axios'
const data = ref(null)
let timer = null
const fetchData = async () => {
try {
const response = await axios.get('/api/data')
data.value = response.data
} catch (error) {
console.error('获取数据失败', error)
}
}
onMounted(() => {
fetchData() // 组件加载时先执行一次
timer = setInterval(fetchData, 5000) // 每5秒请求一次
})
onUnmounted(() => {
clearInterval(timer) // 组件卸载时清除定时器,以免引起内存泄漏
})
</script>
<template>
<div>
<h3>普通轮询示例</h3>
<pre>{{ data }}</pre>
</div>
</template>
-这样的缺点是,
- 1,会造成性能的浪费,造成网页和服务器资源的浪费,有一些请求返回的是没有变化的数据
- 2,数据更新不及时,有可能数据的更新位于两次轮询请求之间,距离下一次轮询请求还有时间间隔
2.长轮询:是一种改进的轮询方式,客户端发送请求到服务端,服务端会等待有数据变化再返回,或者超时。即客户端发送请求到服务端后,服务端保持连接。当数据有更新时,服务端立刻响应返回新数据并关闭连接,客户端收到响应后,会立即发送新请求继续等待;当数据在超时限定时间内无更新,则服务端返回请求超时,客户端重新发起请求等待下一次的数据可能更新。
js
//实现:用axios或者fetch的递归调用
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import axios from 'axios'
const data = ref(null)
let isPolling = true
const longPolling = async () => {
if (!isPolling) return
try {
const response = await axios.get('/api/long-polling', { timeout: 30000 }) // 30秒超时
data.value = response.data
longPolling() // 递归调用,立即发送下一个请求
} catch (error) {
console.error('长轮询失败', error)
setTimeout(longPolling, 2000) // 失败后等待2秒重试
}
}
onMounted(() => {
isPolling = true
longPolling()
})
onUnmounted(() => {
isPolling = false // 组件卸载时停止轮询
})
</script>
<template>
<div>
<h3>长轮询示例</h3>
<pre>{{ data }}</pre>
</div>
</template>