跳至主要内容

如何实现订阅模型

默认情况下,即使另一端没有注册事件处理程序,事件也会通过网络发送。

注意

您可以使用通配符监听器捕获这些缺失的事件处理程序

socket.onAny((event) => {
if (socket.listeners(event).length === 0) {
console.log(`missing handler for event ${event}`);
}
});

参考: onAny() 方法

要仅接收特定事件列表(例如,如果应用程序的一部分只需要少量事件),您可以实现订阅模型

客户端

const subscriptions = [];

function subscribe(topic) {
subscriptions.push(topic);
if (socket.connected) {
socket.emit("subscribe", [topic]);
}
}

function unsubscribe(topic) {
const i = subscriptions.indexOf(topic);
if (i !== -1) {
subscriptions.splice(i, 1);
if (socket.connected) {
socket.emit("unsubscribe", topic);
}
}
}

// restore the subscriptions upon reconnection
socket.on("connect", () => {
if (subscriptions.length && !socket.recovered) {
socket.emit("subscribe", subscriptions);
}
});

subscribe("foo");

服务器

io.on("connection", (socket) => {
socket.on("subscribe", (topics) => {
socket.join(topics);
});

socket.on("unsubscribe", (topic) => {
socket.leave(topic);
});

// send an event only to clients that have shown interest in the "foo" topic
io.to("foo").emit("foo");
});

其他说明

订阅列表

我们本可以在客户端使用 ES6 Set 来进行订阅

const subscriptions = new Set();

function subscribe(topic) {
subscriptions.add(topic);
if (socket.connected) {
socket.emit("subscribe", [topic]);
}
}

function unsubscribe(topic) {
const deleted = subscriptions.delete(topic);
if (deleted && socket.connected) {
socket.emit("unsubscribe", topic);
}
}

// restore the subscriptions upon reconnection
socket.on("connect", () => {
if (subscriptions.size) {
socket.emit("subscribe", [...subscriptions]);
}
});

这更简洁(例如,无需处理重复订阅),但如果您需要针对 旧平台,则需要一个 polyfill。

连接状态恢复

在“连接”处理程序中

socket.on("connect", () => {
if (subscriptions.length && !socket.recovered) {
socket.emit("subscribe", subscriptions);
}
});

!socket.recovered 条件与 连接状态恢复功能 相关。

如果连接状态成功恢复,则订阅(服务器端的房间)将自动恢复。

参考: socket.recovered 属性