假设以下场景: 世界杯决赛期间,我们要实时的记录双方进球数量(前端展示)。
定期轮询
定期向服务器发送请求,例如每10秒向服务器发送一次请求。
缺点:
- 对于进球的情况最多会有10s的延迟
- 频繁的请求消耗性能,不管是否有进球,10s都会向服务器请求一次。
长轮询
浏览器向服务器发送一次请求获取进球情况,服务器端发现数据并未更新于是就原地静静等待(不对请求做出响应,也不关闭连接),然后突然法国进球了!数据更新了!服务器马上做出对之前请求的响应,然后浏览器同时重新发出一个新的请求等待下一次响应。
客户端代码
async function subscribe() {
let response = await fetch("/api/xxx/xxx");
if (response.status == 502) {
// 连接超时重新发送请求
await subscribe();
} else if (response.status != 200) {
await new Promise(resolve => setTimeout(resolve, 1000));
await subscribe();
} else {
// 服务器返回内容显示
let num = await response.text();
alert(`进球数${num}`);
// 再次调用 subscribe() 获取下一条消息
await subscribe();
}
}
subscribe();
优点
- 不依靠特定的协议,是和服务器保持长久连接最简单的方式。
缺点
- 当推送的消息频率很低时长轮询很有效,但是推送较为频繁的时候,每次推送都是一个独立的请求,同样会带来一些性能问题。
Websokct
WebSockets 是一种先进的技术。它可以在用户的浏览器和服务器之间打开交互式通信会话。使用此 API,您可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。 ——MDN
一些常用的基于WebSokcet协议的库
用ws库写一个简单的🌰
服务端
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 3000 });
wss.on('connection', function connection(ws) {
ws.on('message', function message(data) {
console.log('received: %s', data); // reveived: Hello!
});
ws.send('something'); // 给客户端发送的信息
});
客户端代码
// 打开一个WebSocket:
var ws = new WebSocket('ws://localhost:3000/test');
// 响应onmessage事件:
ws.onmessage = function (msg) {
console.log(msg.data); // "something"
};
ws.onopen = function (e) {
// 给服务器发送一个字符串:
ws.send('Hello!');
}