I have express application, which servers some api endpoints and websocket. Web socket have rooms and on every message it inserts message to mongodb.
wsServer.on("connection", (ws, req) => {
const params = url.parse(req.url, true).query;
const token = params.token;
if (!token) {
ws.close(1008, "token required");
}
ws.on("message", (message) => {
const data = JSON.parse(message);
console.log(data.room);
switch (data.type) {
case "join":
if (!rooms[data.room]) {
rooms[data.room] = [];
}
rooms[data.room].push(ws);
ws.room = data.room;
broadcast(ws.room, `User joined room ${ws.room}`);
break;
case "message":
const date = new Date();
insertMessage(
"data",
{
day: date.getDate() + 1,
month: date.getMonth() + 1,
year: date.getFullYear(),
hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds(),
},
ws.room,
data.message
);
broadcast(ws.room, data.message);
break;
}
});
ws.on("close", () => {
if (ws.room && rooms[ws.room]) {
rooms[ws.room] = rooms[ws.room].filter((client) => client !== ws);
broadcast(ws.room, `User left room ${ws.room}`);
}
});
});
For frontend I use React and got this code :
import axios from "axios";
import { useEffect, useState, useCallback } from "react";
import { useNavigate, useParams } from "react-router-dom";
import useWebSocket, { ReadyState } from "react-use-websocket";
const socketURL = "ws://localhost:8080";
const Chat = () => {
const [input, setInput] = useState("");
const [messageHistory, setMessageHistory] = useState([]);
const { room_category } = useParams();
const navigate = useNavigate();
/// THIS WHOLE THING IS FOR WEB SOCKET \
const { sendMessage, lastMessage, readyState } = useWebSocket(
`${socketURL}?token=${localStorage.getItem("token")}`,
{
onOpen: () => {
sendMessage(
JSON.stringify({
type: "join",
room: room_category,
})
);
},
shouldReconnect: (closeEvent) => true,
}
);
useEffect(() => {
if (lastMessage !== null) {
const data = JSON.parse(lastMessage.data);
setMessageHistory((prevMessages) => [...prevMessages, data.message]);
}
}, [lastMessage]);
const connectionStatus = {
0: "Connecting",
1: "Open",
2: "Closing",
3: "Closed",
}[readyState];
useEffect(() => {
if (connectionStatus === "Closed") {
navigate("/home");
}
}, [connectionStatus]);
const handleSendMessage = useCallback(() => {
if (input.trim()) {
sendMessage(
JSON.stringify({
type: "message",
message: input,
})
);
setInput("");
}
}, [input, sendMessage]);
/// THIS WHOLE THING IS FOR WEB SOCKET \
return (
<div>
<h2>Room: {room_category}</h2>
<div>Status: {connectionStatus}</div>
<div>
{messageHistory.map((msg, index) => (
<div key={index}>{msg}</div>
))}
</div>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === "Enter" && handleSendMessage()}
/>
<button onClick={handleSendMessage}>Send</button>
</div>
);
};
export default Chat;
I also have function find user which finds user in db
Async/Await one :
exports.findUser = async ({ id, username, name }) => {
let query;
//checking which data is providedf to set this data to query
if (id) {
query = { _id: new ObjectId(id) };
}
if (username) {
query = { username };
}
if (name) {
query = { name };
}
//finding user with setted query
const user = await usersCollection.findOne(query);
return user;
};
And regular one :
exports.findUser_ = ({ id, username, name }) => {
let query;
// checking which data is provided to set this data to query
if (id) {
query = { _id: new ObjectId(id) };
}
if (username) {
query = { username };
}
if (name) {
query = { name };
}
// finding user with set query
return usersCollection
.findOne(query)
.then((user) => {
return user;
})
.catch((error) => {
console.error("Error finding user:", error);
throw error;
});
};
When I try to run async/await funtion on connection in ws I get unexpected actions. When I try to make it with traditoional .then method I only get one user everytime. how can I verify user using jwt.