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

函数更新后Socket.io未触发客户端事件问题求助

问题分析与解决方案

你的核心问题是重复绑定Socket.io的connection事件,每次调用getRandomGists都会添加新的监听器,导致只有新连接的客户端能收到更新通知,旧客户端完全收不到,同时服务器端会累积大量重复的事件处理逻辑。

修正后的服务器端代码

const PORT = 8080;
const SOCKET_PORT = 3000;
let interval = 5000;
const io = new Server(SOCKET_PORT);

// 维护所有已连接的客户端Socket实例
const connectedClients = new Set();

// 只绑定一次connection事件——服务器启动时执行一次即可
io.on("connection", (socket) => {
  console.log("新客户端已连接");
  connectedClients.add(socket);

  // 客户端断开连接时从集合中移除
  socket.on("disconnect", () => {
    console.log("客户端已断开");
    connectedClients.delete(socket);
  });

  // 监听客户端消息(移到这里,避免重复绑定)
  socket.on("customMessage", (arg) => {
    console.log(arg);
  });
});

const getRandomGists = () => {
  // some vars here
  fetch(rndGist)
    .then((res) => res.text())
    .then((body) => {
      const { window } = new JSDOM(body);
      const { document } = window;
      const codeBlock = document.querySelectorAll(".blob-code-inner");
      const now = new Date().toLocaleTimeString();
      console.log(`rndGist: ${rndGist}. Time: ${now}`);
      return codeBlock;
    })
    .then((codeBlock) => {
      const fauxCode = new FauxCode(codeBlock, options);
      fs.writeFileSync(filename, fauxCode.render());
    })
    .then(() => {
      // 向所有已连接的客户端广播更新消息
      connectedClients.forEach(socket => {
        socket.emit("imageUpdate", "Image updated");
        console.log("已向客户端发送更新通知");
      });
    })
    .catch(err => {
      console.error("处理Gist时出错:", err);
    });
};

getRandomGists();

setInterval(() => {
  getRandomGists();
}, interval);

app.use(express.static("public"));

app.listen(PORT, () => console.log(`Server listening on: ${PORT}`));

修正后的客户端代码

const socket = io("ws://localhost:3000");

socket.on("imageUpdate", (arg) => {
  reloadImg("../img/fauxcode.svg");
  console.log(arg, `reloadImg from client`);
});

function reloadImg(url) {
  const now = new Date().getTime();
  // 修正选择器:去掉多余的转义符,直接用.class选择器
  const wrapper = document.querySelector(".code");
  // 加时间戳避免浏览器缓存旧SVG
  wrapper.setAttribute(`src`, `${url}?timestamp=${now}`);
  socket.emit("customMessage", "Emiting from the client!");
}

关键修复点说明

  1. 只绑定一次connection事件
    Socket.io的io.on("connection")是全局监听器,只需要在服务器启动时绑定一次。重复绑定会导致每次新连接触发N次回调(N是你调用getRandomGists的次数),完全不符合预期。

  2. 维护客户端Socket集合
    用Set存储所有已连接的Socket实例,客户端断开时自动移除。图片更新后,遍历集合向所有在线客户端发送通知,确保旧客户端也能收到更新。

  3. 修正客户端选择器
    原代码中document.querySelector("\.code")的转义符是多余的,浏览器会把\.code当成无效选择器,导致找不到img元素,无法更新src属性。

  4. 添加错误处理
    在Promise链末尾添加catch,避免Gist请求失败时整个流程中断,便于调试问题。

内容的提问来源于stack exchange,提问作者lharby

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 15:19:51