【问题标题】:How to send socket.io messages from several routes using NodeJS如何使用 NodeJS 从多个路由发送 socket.io 消息
【发布时间】:2018-06-28 14:36:11
【问题描述】:

我正在使用 socket.io 在客户端和 NodeJS HTTP 服务器之间发送和接收消息。到目前为止,它运行良好,因为所有代码都在 app.js 主文件中,如下所示:

let express = require('express')
let app = express();

let http = require('http');
let server = http.Server(app);

let socketIO = require('socket.io');
let io = socketIO(server);

io.on('connection', (socket) => {
    console.log('New user connected');

    socket.on('new-message', (message) => {
        console.log(message);

        io.emit('new-message', message);
    });
});

但现在我有这个案例:

  • 当用户从客户端应用程序请求 /compile/save 路由时,服务器需要执行一些操作(每个操作最多需要 2 秒),我想通知他通过发送消息socket.io 显示每个操作的结果。这是一个示例路由处理程序:

routes/compile.js

var express = require('express');

var router = express.Router();

router.get('/compile', (req, res, next) => {
    // DO THE OPERATIONS

    // For each operation, send a socket.io message to the client with the result
});

每个客户端的socket是在主文件中获取的,当它们连接到服务器时(io.on('connection', (socket) => {),那么我如何在路由中使用它呢?

希望我解释清楚,nodeJS/socket.io 组合让我大吃一惊……谢谢!

【问题讨论】:

    标签: node.js socket.io


    【解决方案1】:

    一种简单的方法是将用户加入特定频道,然后发射到该特定频道。

    io.on('connection', (socket) => {
        console.log('New user connected');
    
        const userId = getUserIdSomehow(); // logged user, ip, cookie, or whatever you like
        socket.join(userId); 
    
        socket.on('new-message', (message) => {
            console.log(message);
    
            io.emit('new-message', message);
        });
    });
    

    快速路线

    router.get('/compile', (req, res, next) => {
        // DO THE OPERATIONS
        const userId = getUserIdSomehow(); // ip, cookie, or whatever you like
        io.to(userId).emit('some-event', 'some-data');
        // For each operation, send a socket.io message to the client with the result
    });
    

    您需要将io 实例传递给您的快速路由模块。有多种方法可以做到这一点,检查这个问题:

    What is the best way to pass common variables into separate modules in Node.js?


    另一种方法是使用 cookie 或自定义标头在 HTTP 请求中发送 socketId。

    客户端

    socket.on('connect', function() {
        // Save this session Id, and use it on every request
        const sessionid = socket.socket.sessionid;
        setCookie('socketId', sessionId); // implement setCookie
    });
    

    快速路线

    router.get('/compile', (req, res, next) => {
          // DO THE OPERATIONS
          const userId = req.cookies.socketId;
          io.to(userId).emit('some-event', 'some-data');
          // For each operation, send a socket.io message to the client with the result
     });
    

    Socket.IO 中的每个 Socket 都由一个随机的、不可猜测的、 唯一标识符 Socket#id。为了您的方便,每个插座 自动加入由该 ID 标识的房间

    这种方式的缺点是,如果套接字连接断开,或者如果用户离开,socketId 将发生变化,您将无法发出。如果可以识别并持久化用户的身份,推荐第一种方式。

    【讨论】:

    • 感谢您的快速回复,我将尝试实施第一个解决方案。而且,在快速路由中,您将如何初始化 io 对象?
    • 不客气。您不必初始化它,您需要传递与app.js 相同的io 对象。您需要使用io 的实例。您可以使用多种方法之一将变量传递给其他模块。检查另一个问题:stackoverflow.com/questions/10306185/…
    【解决方案2】:

    按照马科斯的建议,这是我为解决问题所做的:

    app.js

    let socketIO = require('socket.io');
    let io = socketIO(server);
    
    // ROUTES
    let compileRoute = require('./routes/compile')(io);  // Inject the Socket IO object into the routes module
    
    app.use('/compile', compileRoute);
    

    routes/compile.js

    module.exports = function(io) {
        router.post('/', (req, res, next) => {
            var body = req.body;
    
            var sid = body.socketId;  // Socket ID from the client
    
            // OPERATION LOOP
    
            // Use the injected Socket IO object and the socket ID received from the client
            // to send the result messages
            io.to(sid).emit('new-message', 'Operation result');
        });
    
        return router;
    };
    

    角分量

    public doCompile() {
        const body = {
            // Obtain the socket ID from the service (basically, it returns this.socket.id)
            socketId: this.socketService.getSocketId()
        };
    
        // Send the HTTP request with the socket id in the body
        this.httpClient.post('http://localhost:2999/compile', body).subscribe(
    }
    

    现在,我必须管理可能的套接字断开连接,以便在套接字服务中重新分配一个新的套接字 ID,但这是另一个主题 :)

    干杯,

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-20
      • 2020-02-17
      • 2013-06-30
      • 1970-01-01
      • 2018-06-15
      • 2018-01-29
      • 2018-12-24
      相关资源
      最近更新 更多