WebSocket
2023 javascriptWebSocket 是一个持久化的协议,允许服务端主动向客户端推送消息。
构造函数
new WebSocket(url);
new WebSocket(url, portocols);
属性
readyState
readyState
属性返回实例对象的当前状态
- 0: CONNECTING,表示 socket 已经创建,连接未打开。
- 1: OPEN,表示连接已经打开,可以准备通信。
- 2: CLOSING,表示连接正在关闭。
- 3: CLOSED,表示连接已经关闭或者打开失败。
返回一个新的 WebSocket
对象。
binaryType
返回 WebSocket 连接通信的二进制数据格式类型,有 blob
和 arraybuffer
实例方法
send
实例对象的 send() 方法用于向服务器发送数据。
const ws = new WebSocket(url);
ws.send(data);
close
实例对象的 close() 方法用于关闭连接,如果已经关闭了,则不会做任何事。
const ws = new WebSocket(url);
ws.close();
ws.close(code);
ws.close(code, reason);
事件
close
当一个 WebSocket 连接关闭时,触发该事件。
addEventListener('close', (event) => {});
onclose = (event) => {};
error
当一个 WebSocket 连接因为错误而导致关闭时,触发该事件。
addEventListener('error', (event) => {});
onerror = (event) => {};
message
当通过 WebSocket 收到数据时,触发该事件。
addEventListener('message', (event) => {});
onmessage = (event) => {};
open
当一个 WebSocket 连接打开时,触发该事件。
addEventListener('open', (event) => {});
onopen = (event) => {};
心跳检测
心跳检测是让浏览器或服务器定时发送消息,用于检测连接是否正常。可以在发现异常,进行对应的操作,如通知或重连。
以下是一个简单的实现:
/**
* 服务端,
* WebSocket 安装了 ws 库
*/
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({
port: 8080,
});
wss.on('connection', (ws) => {
ws.on('message', (data) => {
console.log('received: %s', data);
if (data.toString() === 'heartbeat') {
ws.send('heartbeat');
}
});
});
/**
* 客户端,收到信息后,隔 5s 发送信息,5s 未收到响应则关闭链接
*/
const ws = new WebSocket('ws://localhost:8080');
const PING_TIEMOUT = 5 * 1000;
const PONG_TIMEOUT = 5 * 1000;
// 发送和接受定时器超时
let pingTimeoutId;
let pongTimeoutId;
ws.addEventListener('open', () => {
console.log('open');
heartbeat();
});
ws.addEventListener('close', () => {
console.log('close');
reset();
});
ws.addEventListener('message', (event) => {
console.log('message::', event.data);
heartbeat();
});
function heartbeat() {
reset();
start();
}
function start() {
pingTimeoutId = setTimeout(() => {
ws.send('heartbeat');
pongTimeoutId = setTimeout(() => {
ws.close();
}, PONG_TIMEOUT);
}, PING_TIEMOUT);
}
function reset() {
clearTimeout(pingTimeoutId);
clearTimeout(pongTimeoutId);
}