Node.js中如何将controller层数据传递给socket.io并向客户端推送
核心实现思路
你只需要将socket.io的实例暴露到controller可以访问的位置,拿到第三方接口数据后直接调用emit方法推送即可,以下是具体实现步骤:
步骤1:挂载socket.io实例到全局可访问位置
推荐挂载到Express的app实例上,适配绝大多数业务场景,修改你的服务启动入口文件(一般为app.ts/server.ts):
import express from 'express' import { Server } from 'socket.io' import http from 'http' import socketInit from './Sockets' import router from './routes' const app = express() const server = http.createServer(app) // 初始化socket.io,跨域配置根据你的实际场景调整 const io = new Server(server, { cors: { origin: "*" } }) // 执行原有socket初始化逻辑 socketInit(io) // 重点:将io实例挂载到app的全局属性上,所有路由控制器都可访问 app.locals.io = io // 注册路由 app.use(router) server.listen(3000, () => console.log('服务启动在3000端口'))
步骤2:修改controller代码,拿到数据后触发推送
修改router.controller.ts,直接从请求对象中获取挂载的io实例,拿到数据后推送:
export const getData: RequestHandler = async (req, res) => { const options= { method: 'GET', }; const response = await fetch(citybikeurl, options) .then((res: any) => res.json()) .catch((e: any) => { console.error({ error: e }); return res.status(500).json({error: '获取数据失败'}) }); console.log("RESPONSE: ", response); // 从全局属性拿到io实例 const io = req.app.locals.io if (io) { // 自定义事件名,这里示例为bikeDataUpdate,前端监听对应事件即可 // io.emit是推送给所有已连接的客户端,如果需要推给指定用户,使用io.to(指定socketId).emit io.emit('bikeDataUpdate', response) } res.json(response); }
步骤3:React前端监听推送事件
前端安装socket.io-client后,监听服务端推送的自定义事件即可实时更新数据:
import { io } from 'socket.io-client' import { useEffect, useState } from 'react' // 连接你的socket服务,地址替换为实际服务地址 const socket = io('http://localhost:3000') function App() { const [bikeData, setBikeData] = useState(null) useEffect(() => { // 监听服务端推送的bikeDataUpdate事件 socket.on('bikeDataUpdate', (data) => { setBikeData(data) }) // 组件卸载时取消监听,避免内存泄漏 return () => { socket.off('bikeDataUpdate') } }, []) // 此处替换为你的实际渲染逻辑 return <div>{JSON.stringify(bikeData)}</div> }
可选实现方案
如果你不想将io实例挂载到app上,也可以单独写一个模块存储io实例:
- 新建
ioInstance.ts:
import { Server } from 'socket.io' let io: Server // 初始化时调用,存储io实例 export const setIoInstance = (ioInstance: Server) => { io = ioInstance } // 业务代码中调用,获取io实例 export const getIoInstance = () => io
- 服务初始化时调用
setIoInstance(io),controller中直接导入getIoInstance即可拿到io实例。
注意事项
- 如果你的业务是定时拉取第三方数据推送给前端,不需要走HTTP接口的话,也可以直接把定时拉取逻辑写在
Sockets.ts里,拿到数据直接通过io推送即可。 - 注意单独配置socket.io的跨域规则,避免前端连接失败。
- 前后端监听/触发的事件名要保持一致。
内容的提问来源于stack exchange,提问作者alexmejia992
相关产品推荐
相关产品推荐

