前端 WebSocket 实战:从轮询到实时通信
为什么需要 WebSocket
在开发实时功能时,很多开发者习惯用 HTTP 轮询。想象一下,每隔一分钟就去敲门问'好了没',不仅烦人还低效。最近看到一个项目,实时聊天功能每秒请求一次服务器,这种实现方式对带宽和服务器资源的消耗简直是灾难。
反面教材:轮询的代价
// 轮询获取数据
function startPolling() {
setInterval(async () => {
const response = await fetch('/api/messages');
const messages = await response.json();
updateMessages(messages);
}, 1000); // 每秒请求一次
}
这种写法会让服务器不堪重负。每秒发起一次请求,相当于让服务器变成一只不停采蜜的蜜蜂,效率极低且浪费资源。
基础实现:封装一个客户端类
原生 WebSocket API 虽然强大,但直接调用往往需要处理大量细节,比如重连、状态监听等。封装一个类可以让代码更整洁。
// 基础 WebSocket 客户端封装
class WebSocketClient {
constructor(url) {
this.url = url;
this.ws = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
this.listeners = new Map();
}
connect() {
this.ws = (.);
.. = {
.();
. = ;
.();
};
.. = {
data = .(event.);
.(data., data.);
};
.. = {
.();
.();
.();
};
.. = {
.(, error);
.(, error);
};
}
() {
(. && .. === .) {
..(.({ type, payload }));
}
}
() {
(!..(event)) {
..(event, []);
}
..(event).(callback);
}
() {
(..(event)) {
..(event).( (data));
}
}
() {
(. < .) {
.++;
.();
( .(), );
}
}
() {
(.) {
..();
}
}
}
ws = ();
ws.(, { .(); });
ws.(, { .(, data); });
ws.();


