函数更新后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!"); }
关键修复点说明
只绑定一次
connection事件
Socket.io的io.on("connection")是全局监听器,只需要在服务器启动时绑定一次。重复绑定会导致每次新连接触发N次回调(N是你调用getRandomGists的次数),完全不符合预期。维护客户端Socket集合
用Set存储所有已连接的Socket实例,客户端断开时自动移除。图片更新后,遍历集合向所有在线客户端发送通知,确保旧客户端也能收到更新。修正客户端选择器
原代码中document.querySelector("\.code")的转义符是多余的,浏览器会把\.code当成无效选择器,导致找不到img元素,无法更新src属性。添加错误处理
在Promise链末尾添加catch,避免Gist请求失败时整个流程中断,便于调试问题。
内容的提问来源于stack exchange,提问作者lharby
相关产品推荐
相关产品推荐

