我正在使用React / Redux / Socketio构建一个语言交换/聊天应用程序,我碰壁了。
我为redux编写了简单的socketio中间件,以处理我的自定义套接字操作,并且我正在全局共享套接字连接。 我在componentDidMount上添加了事件监听器
componentDidMount() {
const { id, socketSubscribe, receiveTalksList } = this.props;
socketSubscribe('sendTalksList', receiveTalksList);
socketSubscribe('message', messageHandler);
socketSend('getTalksList', id);
}
并在componentWillUnmount上将其删除
componentWillUnmount() {
const { socketUnsubscribe } = this.props;
socketUnsubscribe('sendTalksList');
socketUnsubscribe('message');
}
问题是我希望即使在组件卸载后也能够侦听套接字事件。例如,即使我在用户个人资料页面/组件上,我也想接收“消息”事件。
因此立即想到的是“不要取消订阅这些事件”。但是,在这种情况下,事件侦听器在每个componentDidMount上都是重复的。
为避免这种重复,我在socketio中间件中尝试这样做
if (action.type == types.SOCKET_SUBSCRIBE && action.handler) {
if (socket.listeners(action.event).length > 0 || socket.listeners(action.event).includes(action.handler)) return;
socket.on(action.event, action.handler);
return;
}
socket.listeners(action.event).includes(action.handler)
检查基本上是没有意义的,因为每次安装组件时都会构造一个新实例,因此messageHandler是一个新的函数对象,因此无法检查是否相等。
虽然socket.listeners(action.event).length > 0
可以防止重复事件,但我只能为每个事件附加一个处理程序。
这意味着其他组件无法订阅“消息”事件。
我唯一能想到的就是将侦听器转换为字符串并进行字符串比较。这是非常丑陋和不可靠的。
if (socket.listeners(action.event).filter(listener => listener.toString() === action.handler.toString()).length > 0) return;
是否只有一种方法可以注册所有这些处理程序?我考虑过要创建一些类似于容器/父类的元素,该元素在第一次加载应用程序时就注册所有事件(甚至在主路由器中注册所有处理程序),但是它必须具有对所有处理程序和状态的所有引用可能在那个时间点甚至不可用的变量。
有什么想法吗?