本文へスキップ

サブスクリプションモデルの実装方法

デフォルトでは、イベントは、相手側に登録されたイベントハンドラーがない場合でも、ワイヤーを介して送信されます。

注記

キャッチオールリスナーを使用して、これらの欠落しているイベントハンドラーをキャッチできます。

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]);
}
});

これはよりクリーンです(たとえば、重複したサブスクリプションを処理する必要はありません)。ただし、古いプラットフォームをターゲットにする必要がある場合は、ポリフィルが必要です。

接続状態の復元

"connect"ハンドラー内

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

!socket.recovered条件は、接続状態の復元機能に関連しています。

接続状態が正常に復元された場合、サブスクリプション(サーバー側のルーム)は自動的に復元されます。

参照: socket.recovered 属性