发送几条消息后,WebSocket readyState 停留在 0
Posted
技术标签:
【中文标题】发送几条消息后,WebSocket readyState 停留在 0【英文标题】:WebSocket readyState stuck at 0 after a couple of messages are sent 【发布时间】:2021-05-18 00:17:03 【问题描述】:我正在尝试使用 Web 套接字开发一个实时聊天应用程序并做出反应,但是在我尝试提交几条消息(大约 30 条)后,Web 套接字卡在了 CONNECTING 状态。我已经设置好了,所以当它发送消息时,它禁用了发送按钮,以防止用户发送垃圾邮件太快,但不幸的是我仍然遇到同样的问题。
// id is a uuid() string
const ws = new WebSocket(`ws://localhost:3001/chat/$id`);
useEffect(() =>
ws.onmessage = function(evt)
try
const user_id = parseInt(evt.data.split("")[0]);
const message = evt.data.slice(1);
const currentTime = new Date();
const currentUTC = currentTime.toUTCString();
const timestamp = new Date(currentUTC);
setMessages(messages => [...messages, user_id, message, timestamp])
catch(e)
console.log(e);
ws.onclose = function(evt)
console.log("DISCONNECTED!!")
ws.close();
ws.onerror = function(evt)
console.log(evt);
ws.close();
, []);
useEffect(() =>
async function postMessageToAPI()
const messsageToSend =
unique_id: id,
message: formData.message,
user_id: user.id,
group_chat_id: room.id
// Convert to unviersal time UTC and send it to database
let currentUTC = new Date();
currentUTC.toUTCString();
messsageToSend.timestamp = currentUTC;
await AnonChatApi.sendChatMessage(messsageToSend);
if(sendMessage)
ws.onopen = function()
// add user_id to the start of the message string
const message = `$user.id` + formData.message;
ws.send(message);
postMessageToAPI();
resetFormData();
setTimeout(() =>
setSendMessage(false)
, 1000);
, [sendMessage]);
const goBackHome = () =>
ws.close();
history.push('/');
【问题讨论】:
你没有显示打开或关闭套接字的代码,你能补充一下吗? 如果您在每条消息后都关闭套接字,那么您可能不应该使用 websocket。我无法从您的代码中判断是否是这种情况,但您的描述似乎暗示了这一点。 @Codebling,我添加了打开和关闭 websocket 的代码。我不是在每条消息后都尝试关闭 websocket,我只是通过一次发送多条消息来测试错误,它最终卡在 readyState 0 上。感谢您查看我的代码! 【参考方案1】:我可以看到您正在使用 Hooks,因此您还必须使用功能组件。 我认为初始化 websocket 的代码是否正确
const ws = new WebSocket(`ws://localhost:3001/chat/$id`);
在函数的顶部?
提醒一下,每当你的组件被渲染时,定义你的函数组件的函数就会运行。任何未保存在状态中的东西都会丢失。这包括你的 websocket - 每次渲染都会创建一个新的 websocket,你的异步函数可能会在旧的 websocket 上发送数据(来自以前的渲染),React 可能会在控制台中警告你有内存泄漏。
useEffect
是这里的正确做法,但是 websocket 也需要保存在 state 中。
YourFunctionComponent()
const [ws, setWs] = useState(null);
useEffect(() =>
if (ws == null)
setWs(new WebSocket(`ws://localhost:3001/chat/$id`));
return () =>
// A function returned from useEffect will
// get called on component unmount.
// Use this function to clean up your connection and
// close your websocket!
// clean up, e.g.
// ws.send('closing due to unmount!');
ws.close();
setWs(null);
, [ws, setWs]);
// Add `ws` as a dependency in the useEffect()s you posted above
useEffect(() =>
ws.onmessage = function(evt)
[--snip--]
, [ws]);
useEffect(() =>
async function postMessageToAPI()
[--snip--]
, [sendMessage, ws]);
【讨论】:
解决了这个问题,谢谢!我还需要添加检查以等待设置 ws 否则我会收到诸如“无法读取 null 的消息”之类的错误。 @Allen 真棒!以上是关于发送几条消息后,WebSocket readyState 停留在 0的主要内容,如果未能解决你的问题,请参考以下文章