如何使用 NodeJS 从多个路由发送 socket.io 消息



我正在使用 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 发送消息以显示每个操作的结果。下面是一个示例路由处理程序:

路由/编译.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 组合让我大吃一惊......谢谢!

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

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实例传递给快速路由模块。有多种方法可以做到这一点,请检查这个问题:

将公共变量传递到 Node.js 中的单独模块的最佳方法是什么?


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

客户端

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 中的每个套接字都由随机的、不可猜测的、 唯一标识符套接字#id。为了您的方便,每个插座自动加入由此 ID 标识的聊天室

这种方式的缺点是,如果套接字连接断开,或者用户离开,socketId 将更改,您将无法发出。如果可以标识并保留用户的标识,则建议使用第一种方法。

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

应用.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);

路由/编译.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,但这是另一个主题:)

干杯

最新更新