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

Express JS项目不同控制器中调用Socket IO发送消息的实现问题

解决方案

步骤1:将Socket IO实例挂载到Express全局上下文

修改server.js初始化逻辑,把IO实例绑定到Express的app对象上,方便全局调用:

const express = require('express')
const http = require('http')
const { Server } = require('socket.io')
const app = express()
const server = http.createServer(app)
const io = new Server(server, {
  // 按需配置跨域等参数
  cors: { origin: "*" }
})

// 关键步骤:将io实例挂载到app全局属性
app.set('io', io)

// 原有连接监听逻辑
io.on('connection', (socket) => {
    socket.emit('message', 'This is a test message from the server.')
})

// 后续挂载路由、启动服务等逻辑保持不变
// app.use('/api', yourRouter)
server.listen(3000, () => console.log('服务启动在3000端口'))

步骤2:在控制器中调用Socket IO实例

Express控制器的request对象自带app属性,可以直接获取到挂载的io实例,可根据需求选择广播或者定向发送消息:

const getComments = asyncHandler(async (request, response) => {
    // 从request对象中获取全局io实例
    const io = request.app.get('io')
    const { liveID, token: accessToken } = request.body
    var source = new EventSource(
        `https://streaming-graph.facebook.com/${liveID}/live_comments?access_token=${accessToken}&comment_rate=one_per_two_seconds&fields=from{name,id},message`
    )
    source.onmessage = function (event) {
        const commentData = JSON.parse(event.data)
        // 场景1:给所有已连接的客户端广播评论数据
        io.emit('new-live-comment', commentData)

        // 场景2:如果需要定向发给指定用户(比如仅当前请求的发起者)
        // 需要提前绑定用户ID和socket.id,参考补充说明的逻辑
        // const targetSocketId = global.userSocketMap.get(request.user.id)
        // targetSocketId && io.to(targetSocketId).emit('new-live-comment', commentData)
    }
    source.onerror = function (error) {
        console.log('Error!')
        console.log(error)
    }

    source.onopen = function (event) {
        console.log(event)
    }
    // 按需提前返回响应,无需等待EventSource结束
    response.status(200).json({ status: 'ok', msg: '评论流监听已启动' })
})

补充说明(定向发送可选)

如果需要实现用户级别的定向消息发送,可以在Socket连接时存储用户和SocketID的映射关系,修改server.js的connection逻辑即可:

// 单实例部署可以用Map存储,分布式部署可以替换为redis
const userSocketMap = new Map()
io.on('connection', (socket) => {
    // 客户端连接时在query参数携带用户ID做身份绑定
    const userId = socket.handshake.query.userId
    if(userId) {
        userSocketMap.set(userId, socket.id)
    }
    socket.emit('message', 'This is a test message from the server.')
    // 断开连接时删除映射避免内存泄漏
    socket.on('disconnect', () => {
        userId && userSocketMap.delete(userId)
    })
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:36:01