我正在使用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
路由时,服务器需要执行一些操作(每个操作最多需要2s),我想保留他通过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的组合让我很惊讶...谢谢!
答案 0 :(得分: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将更改,并且您将无法发出该消息。如果您可以识别并保持用户的身份,则建议采用第一种方法。
答案 1 :(得分:0)
根据Marcos的建议,这是我为解决该问题所做的事情:
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,但这是另一个主题:)
干杯