我是 socket.io 的新手。我正在使用 socket.io 開發實時通知功能。一切正常。但是在重新加載瀏覽器時,用戶的 socketId 會發生變化,并且通知功能不起作用。我的問題是如何在瀏覽器重繪 時跟蹤新的 socketId。
//server.js-> socket.io code
const io = new Server(server, {
cors: {
origin: "http://localhost:3000",
},
});
let onlineUsers: any = [];
const addNewUser = (username: any, socketId: any) => {
!onlineUsers.some((user: any) => user.username === username) &&
onlineUsers.push({ username, socketId });
console.log("o", onlineUsers);
};
const getUser = (username: any) => {
return onlineUsers.find((user: any) => user.username === username);
};
io.on("connection", (socket) => {
console.log("a user connected");
console.log(socket.id);
socket.on("newUser", (username: any) => {
console.log("username", username);
// console.log("socketId", socket);
addNewUser(username, socket.id);
});
socket.on("sendNotification", ({ senderName, receiverName, action }) => {
const receiver = getUser(receiverName);
io.to(receiver?.socketId).emit("getNotification", {
senderName,
action,
});
});
socket.on("disconnect", () => {
console.log("user disconnected");
});
});
//client side socket.io code
useEffect(() => {
setSocket(io("http://localhost:5000"));
}, []);
useEffect(() => {
const userData: any = localStorage.getItem("user");
setUser(JSON.parse(userData)?.name);
// console.log("userId", userId, socket.emit);
if (user) {
socket?.emit("newUser", user);
}
}, [socket, user]);
//navbar component
React.useEffect(() => {
socket?.on("getNotification", (data: any) => {
console.log("data2", data);
setNotifications((prev): any => [...prev, data]);
});
}, [socket]);
請嘗試詳細說明您的答案/建議或參考。
uj5u.com熱心網友回復:
我不知道這在socket.io中是否可行,它應該在重繪 時獲得一個新的套接字ID,但你也許可以用IP地址做點什么?也許使用其中之一:
socket.handshake.headers["x-forwarded-for"], socket.handshake.headers["x-real-ip"], or socket.handshake.address.
您可以保留一個“ipmap”陣列并將這些值添加到連接地圖并以這種方式跟蹤用戶,因為重繪 瀏覽器時 IP 地址不會改變。
uj5u.com熱心網友回復:
我找到了解決這個問題的方法。可能這不是完美的解決方案,但應該完成作業。向其他人解釋解決方案。
實際上,問題出在這個函式上
const addNewUser = (username: any, socketId: any) => {
!onlineUsers.some((user: any) => user.username === username) &&
onlineUsers.push({ username, socketId });
};
我撰寫了這個函式來避免onlineUsers陣列中的重復資料。當我重新加載瀏覽器時,socketId它發生了變化,但它username是一樣的。所以沒有資料被推送到onlineUsers陣列中。
現在,我寫這個函式而不是上面的函式
const addNewUser = (username: any, socketId: any) => {
if (onlineUsers.length === 0) {
onlineUsers.push({ username, socketId });
}
if (onlineUsers.length > 0) {
onlineUsers = onlineUsers.filter((user: any) => user.username !== username);
onlineUsers.push({ username, socketId });
}
};
現在新的用戶資料替換了onlineUsers陣列中相同的舊用戶資料,并且在重新加載后可以正常作業。
uj5u.com熱心網友回復:
我會建議一個更簡單的方法。而不是使用 socket.id 創建一個具有用戶唯一 ID 的房間(存盤在 DB 中)。現在在該房間(用戶的唯一 ID)上發出和接收通知。
io.on("connection", async (socket) => {
socket.on("joinrooms", async (data) => {
socket.join(data.userId);
});
socket.on("sendMessage", async (data) => {
console.log("message", data);
io.to(data.userId).emit("sendMessage", data);
});
});
/* Must Read section
Joinrrom data sample
data={
userId:123 //User's unique id.
}
sendMessage data sample
data={
userId:123, //User's unique id.
}
Here I'm creating a room from the user's unique id(stored in DB) so whenever I
want to send to a particular user I will emit an
event("io.to(data.userId).emit") using the user's
a unique id that way everything will be handled using userId instead of
socketId so now doesn't matter how many socketId is created.
*/
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/524255.html
