TLDR 我试图了解套接字在选项卡之间的行为方式以及如何不在同一应用程序的两个不同选项卡上同时建立两个连接。
我有一个 React 应用程序。当我成功登录我的应用程序时,我点击了 useEffect 来建立套接字连接。这是我的路线组件中。
useEffect() => {
if (auth) {
socketService.connect();
socketService.onMessage(...callback function)
}
}, [auth]);
然后我需要导航到该应用程序中的另一个组件,但我只能通过 url 来执行此操作(没有故意进行内部导航)。
当我这样做时,我需要连接到上面的 onMessage 回调,并加入一个房间/监听这个新组件中的消息。
通过 URL 导航的组件:
useEffect(() => {
**ISSUE: this room is never joined, because no socketService connection is established in this new tab. Why?**
socketService.joinRoom(windowQueueRoom);
socketService.onMessage(...callback function);
}, []);
如果我在这个(^)useEffect中使用socketService.connect(),除了在我的路由文件中建立的连接之外,还会建立第二个连接。
要管理同一应用程序的多个选项卡之间的socket.io连接,并避免建立多个连接,可以通过以下方式处理:
这是一个简单的方法:
第 1 步:跟踪连接状态
在 socketService.connect() 方法中,在建立新连接之前,检查 localStorage 以查看另一个选项卡是否已打开连接。
function connect() {
if (localStorage.getItem('socketConnected') === 'true') {
console.log('Socket already connected in another tab.');
return;
}
// Proceed to connect the socket
socket = io.connect(); // your connection code here
localStorage.setItem('socketConnected', 'true');
// Clean up when the tab is closed or refreshed
window.addEventListener('beforeunload', () => {
socket.disconnect();
localStorage.setItem('socketConnected', 'false');
});
}
第 2 步:监听 localStorage Events
您可以侦听 localStorage 事件以了解另一个选项卡何时连接或断开与套接字的连接。这样,选项卡就可以了解彼此的连接状态。
在每个选项卡中,您可以监听这样的存储事件:
window.addEventListener('storage', (event) => {
if (event.key === 'socketConnected' && event.newValue === 'false') {
// Another tab has disconnected the socket, so you can now connect.
socketService.connect();
}
});
第3步:在其他组件中处理重连逻辑
在需要加入房间或监听消息的组件中,在主选项卡中检查套接字是否已连接。如果已连接,请继续加入房间并收听消息。
useEffect(() => {
if (socketService.isConnected()) {
socketService.joinRoom(windowQueueRoom);
socketService.onMessage(...callback function);
} else {
console.log('No socket connection. Waiting for connection to be established.');
}
}, []);
2。使用BroadcastChannel进行通信
或者,您可以使用 BroadcastChannel API 来协调选项卡之间的套接字连接。这允许同一应用程序的不同选项卡之间进行通信。
在一个选项卡中,连接到套接字后,广播该信息:
const channel = new BroadcastChannel('socket-channel');
function connect() {
if (!socket) {
socket = io.connect(); // Connect to socket
channel.postMessage('connected');
}
}
在其他选项卡中,收听广播:
const channel = new BroadcastChannel('socket-channel');
channel.onmessage = (event) => {
if (event.data === 'connected') {
console.log('Socket connected in another tab.');
// You can now proceed with any component logic.
}
};
总结
这可确保只有一个选项卡维护套接字连接,从而防止多个同时连接。