跳到主要內容

如何實作訂閱模型

預設情況下,即使另一端沒有註冊事件處理常式,事件也會透過網路傳送。

注意事項

您可以使用萬用監聽器來捕捉那些遺失的事件處理常式

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 屬性