node.js - 如何在用户与 socket.io 中的聊天室断开连接时显示消息
问题描述
我正在做一个有聊天室的项目。消息传递和加入消息工作正常,但我不知道当有人断开连接时如何显示消息。正如您将在下面的代码中看到的,我对 socket.io 了解不多。
(编辑)
服务器代码(Express/Node)
io.on('connection', socket => {
socket.on('message', ({ name, message }) => {
io.emit('message', { name, message })
})
socket.on('join' , (name)=>{
console.log(name);
socket.broadcast.emit("join" , name.usnm.toUpperCase() + " just joined")
})
socket.on('pre_disconnect', (name) => {
console.log(name);
socket.broadcast.emit("pre_disconnect" , name.usnm.toUpperCase() + " just left")
})
})
客户端代码(React.js)
const socketRef = useRef()
useEffect(
() => {
socketRef.current = io.connect("http://localhost:4000")
socketRef.current.on("message", ({ name, message }) => {
setChat([ ...chat, { name, message } ])
})
socketRef.current.on("join", (usnm) => {
setChat([ ...chat, {name:usnm} ])
})
socketRef.current.on("pre_disconnect", (usnm) => {
setChat([ ...chat, {name:usnm} ])
})
},
[ chat ]
)
useEffect(
() => {
let usnm = sessionStorage.getItem("User");
socketRef.current.emit("join" ,{usnm});
return () => {
socketRef.current.emit("pre_disconnect" ,{usnm});
socketRef.current.disconnect()
}
},
[ ]
)
在上面的代码pre_disconnect
中没有做任何事情。无论有没有它,代码的工作方式都是一样的。
解决方案
- 在服务器应用程序中,定义一个
pre_disconnect
与事件类似的join
事件。
io.on('connection', socket => {
socket.on('message', ({ name, message }) => {
io.emit('message', { name, message })
})
socket.on('join', (name) => {
console.log(name);
socket.broadcast.emit("join" , name.usnm.toUpperCase() + " just joined")
})
// Fire this before disconnecting the socket
socket.on('pre_disconnect', (name) => {
console.log(name);
socket.broadcast.emit("pre_disconnect" , name.usnm.toUpperCase() + " just left")
})
})
- 在第一个
useEffect
钩子调用中,每次有chat
状态更新时都会建立并关闭一个新的套接字连接。这意味着当前会话中的消息数量将由套接字连接/断开的数量生成。来自 React 文档
效果的默认行为是在每次完成渲染后触发效果。这样,如果其依赖项之一发生更改,则始终会重新创建效果。但是,在某些情况下,这可能有点矫枉过正,例如上一节中的订阅示例。我们不需要在每次更新时都创建一个新订阅,只要源属性发生了变化。要实现这一点,请将第二个参数传递给 useEffect,它是效果所依赖的值数组。
同样,除非您明确需要在每次chat
更新时创建和关闭新连接,否则出于性能原因避免使用它。
- 在反应应用程序中,在调用之前
pre_disconnect
使用 , 触发事件并添加类似于.usnm
socketRef.current.disconnect()
join
const socketRef = useRef()
useEffect(() => {
// socketRef.current = io.connect("http://localhost:4000")
if (socketRef.current) {
// Add socketRef as dependency and check if socketRef.current exists then continue with listeners
socketRef.current.on("message", ({ name, message }) => {
setChat([...chat, { name, message }]);
});
socketRef.current.on("join", (usnm) => {
setChat([...chat, { name: usnm }]);
});
// handler for disconnect message
socketRef.current.on("pre_disconnect", (usnm) => {
setChat([...chat, { name: usnm }]);
});
}
// return () => socketRef.current.disconnect()
}, [chat, socketRef]);
useEffect(
() => {
// Here, creates a socket connection only when component renders the first time. Similar to componentDidMount() in class components
socketRef.current = io.connect("http://localhost:4000")
let usnm = sessionStorage.getItem("User");
socketRef.current.emit("join" ,{usnm});
// Disconnect the socket when component is to be unmounted from DOM. Similar to componentWillUnmount() in class components
return () => {
socketRef.current.emit("pre_disconnect" ,{usnm});
socketRef.current.disconnect()
}
},
[ ]
)
编辑:
您收到该错误是因为socketRef
未初始化。我已添加socketRef
为依赖项并将代码包装在if
条件中。请检查更改。
推荐阅读
- java - 收到错误 java.lang.IllegalArgumentException
- android - 如何使用 XPath 根据其子元素查找父元素
- python-3.x - 我如何正则表达式三次方程的系数?
- r - 从字符串中解析每个数字并存储在 R 的新列中
- reactjs - 链接标签不起作用并直接指向要求页面
- python - 解析我的代码时出现意外的EOF?为什么会这样?
- python - 哪个python图形库用于移动点
- java - 如何创建一个可以存储对象的类?
- c - 动态结构初始化和计数器实现
- python-3.x - 在不使用算术运算的情况下计算两个二进制字符串的总和需要多少次迭代?