如何在客户端JS及Socket.IO中获取查询字符串实现私聊功能
实现方案
客户端修改
- 首先优化点击用户的交互,避免a标签跳转刷新导致Socket连接断开,直接通过点击事件存储接收方ID,不需要依赖URL查询字符串,如果你坚持要用查询字符串也同步提供获取方法:
- 全局声明存储当前选中接收方的变量
let currentReceiverId = null- 修改
outputActiveUsers方法,移除a标签,绑定点击事件存储接收方ID
function outputActiveUsers(msg){ console.log("receiver ID", msg.id); console.log("receiver socket id", socket.id); let li=document.createElement("li"); li.classList.add("active-people-li"); // 点击选中用户时存储ID li.addEventListener('click', () => { currentReceiverId = msg.id // 可自行添加选中样式提示用户当前聊天对象 document.querySelectorAll('.active-people-li').forEach(item => item.classList.remove('selected')) li.classList.add('selected') }) li.innerHTML= `<div class="active-sidebar"> <div class="div-of-img"> <img src="../files/profile.png" alt="" class="active-profile-img"> </div> <div> <h4>${msg.name}</h4> <h5>Hi. Is this you, bro?</h5> </div> </div>`; document.querySelector(".the-ul").appendChild(li); }- 提交消息时校验接收方ID,携带ID发送给服务端
如果你坚持要用URL查询字符串的方式,添加如下方法获取参数:chatForm.addEventListener("submit", (event)=>{ event.preventDefault(); if(!currentReceiverId) { alert('请先选择要发送的用户') return } let msgInput=document.querySelector("#msg-input").value.trim(); if(!msgInput) return // 把接收方ID一起传给服务端 socket.emit("privateMsg", { content: msgInput, receiverId: currentReceiverId }); document.querySelector("#msg-input").value=""; document.querySelector("#msg-input").focus(); })function getQueryParam(name) { const urlParams = new URLSearchParams(window.location.search) return urlParams.get(name) } // 页面加载时获取接收方ID window.addEventListener('load', () => { currentReceiverId = getQueryParam('receiverID') })
服务端修改
- 首先维护用户ID和Socket实例的映射表,方便定向发送消息
- 新增私聊消息事件处理,区分全局广播和私人发送
let http=require("http"); let socketio=require("socket.io"); // 新增用户ID和Socket的映射表 const userSocketMap = new Map() let users={}; let send=[]; io.on("connection", async (socket)=>{ console.log("new WS connection"); socket.on("login", async function(user_id){ socket.handshake.session.user_id = user_id; socket.handshake.session.save(); // 登录时存储用户和socket的映射 socket.userId = user_id userSocketMap.set(user_id, socket) }); socket.on("logout", function(user_id){ if(socket.handshake.session.user_id){ delete socket.handshake.session.user_id; socket.handshake.session.save(); // 登出时删除映射 userSocketMap.delete(user_id) } }); socket.on("disconnect", async ()=>{ // 断开连接时删除映射 if(socket.userId) { userSocketMap.delete(socket.userId) } }) // 新增私聊事件处理 socket.on("privateMsg", async data => { const senderId = socket.handshake.session.user_id const { content, receiverId } = data const sender = await User.findById(senderId); const formattedMsg = utils.formatMessage(sender.name, content, senderId, receiverId) // 给发送方自己发消息 socket.emit("chatMsg", formattedMsg) // 给接收方发消息,如果接收方在线的话 const receiverSocket = userSocketMap.get(receiverId) if(receiverSocket) { receiverSocket.emit("chatMsg", formattedMsg) } // 可自行扩展离线逻辑:接收方不在线时将消息存入数据库,等用户上线后推送 }) })
内容的提问来源于stack exchange,提问作者FiFi
相关产品推荐
相关产品推荐

