You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在客户端JS及Socket.IO中获取查询字符串实现私聊功能

实现方案

客户端修改

  • 首先优化点击用户的交互,避免a标签跳转刷新导致Socket连接断开,直接通过点击事件存储接收方ID,不需要依赖URL查询字符串,如果你坚持要用查询字符串也同步提供获取方法:
    1. 全局声明存储当前选中接收方的变量
    let currentReceiverId = null
    
    1. 修改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);
    }
    
    1. 提交消息时校验接收方ID,携带ID发送给服务端
    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();
    })
    
    如果你坚持要用URL查询字符串的方式,添加如下方法获取参数:
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 08:27:01