如何正确使用 Socket.IO 在文件更新后向所有客户端广播事件-js教程

本文详解 socket.io 事件未触发的根本原因:错误地在每次数据处理时重复注册连接监听器;提供标准服务端架构——全局初始化 socket.io、集中管理客户端连接,并在文件写入完成后批量广播事件,确保实时性与可扩展性。

在你提供的代码中,socket.emit(“imageUpdate”, …) 始终不生效的核心问题在于:将 io.on(“connection”, …) 错误地嵌套在了异步链(.then())内部。这意味着每次调用 getRandomGists() 时,都在尝试为 未来可能建立的连接 添加一个新的监听器,而非向 已存在的活跃客户端 发送消息。更严重的是,由于该逻辑位于 fetch → fs.writeFileSync 链之后,它甚至不会在首次连接时执行(因为此时连接早已建立),导致 emit 永远不会被调用。

✅ 正确架构:分离连接管理与业务触发

Socket.IO 的标准实践是:

  • 服务启动时一次性初始化并监听 connection 事件;
  • 将所有活跃 socket 实例缓存(如数组或 Map);
  • 在业务逻辑完成(如 SVG 文件写入成功)后,遍历缓存向所有客户端 emit。

以下是重构后的完整服务端代码(关键修复 + 健壮性增强):

const PORT = 8080;
const SOCKET_PORT = 3000;
const interval = 5000;

// ✅ 1. 全局初始化 Socket.IO 服务器
const io = new Server(SOCKET_PORT);

// ✅ 2. 全局维护活跃客户端列表(推荐用 Set 更安全)
const clients = new Set();

io.on("connection", (socket) => {
  console.log(`Client connected: ${socket.id}`);
  clients.add(socket);

  // 监听客户端自定义消息(可选)
  socket.on("customMessage", (arg) => {
    console.log("[Server] Received custom message:", arg);
  });

  // ✅ 自动清理断开连接的客户端
  socket.on("disconnect", () => {
    console.log(`Client disconnected: ${socket.id}`);
    clients.delete(socket);
  });
});

// ✅ 3. 业务函数:只负责获取、渲染、写入、通知,不涉及 Socket 初始化
const getRandomGists = async () => {
  try {
    const response = await fetch(rndGist);
    if (!response.ok) throw new Error(`HTTP ${response.status}`);

    const body = await response.text();
    const { window } = new JSDOM(body);
    const { document } = window;
    const codeBlock = document.querySelectorAll(".blob-code-inner");

    console.log(`Fetched gist: ${rndGist}. Time: ${new Date().toLocaleTimeString()}`);

    const fauxCode = new FauxCode(codeBlock, options);
    fs.writeFileSync(filename, fauxCode.render());

    // ✅ 4. 关键:向所有当前在线客户端广播更新事件
    for (const socket of clients) {
      try {
        socket.emit("imageUpdate", { 
          message: "Image updated", 
          timestamp: Date.now() 
        });
      } catch (err) {
        console.warn(`Failed to emit to socket ${socket.id}:`, err.message);
        clients.delete(socket); // 清理异常 socket
      }
    }
    console.log(`✅ Broadcasted imageUpdate to ${clients.size} client(s)`);

  } catch (err) {
    console.error("[getRandomGists] Error:", err);
  }
};

// 启动定时任务
setInterval(getRandomGists, interval);

// 启动 HTTP 服务
app.use(express.static("public"));
app.listen(PORT, () => console.log(`HTTP server listening on http://localhost:${PORT}`));
console.log(`Socket.IO server listening on ws://localhost:${SOCKET_PORT}`);

? 客户端优化建议

你的客户端逻辑基本正确,但存在两个小问题需修正:

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » 如何正确使用 Socket.IO 在文件更新后向所有客户端广播事件-js教程
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4023222+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4023222+
  • 本周更新: 0+
  • 最后更新: 2026-03-16