如何在Express 4路由中使用socket.io向连接的套接字发送事件?

时间:2021-07-20 17:54:14

This is a question other people have asked, but I can't manage to benefit from the answers they've been given, due to the different Express setup I have.

这是其他人提出的问题,但由于我的Express设置不同,我无法从他们给出的答案中受益。

I've got socket.io implemented and working in a simple way on my server. This is how it works:

我已经实现了socket.io并在我的服务器上以一种简单的方式工作。这是它的工作原理:

In bin/www:

#!/usr/bin/env node
var debug = require('debug')('gokibitz');
var app = require('../../server');

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
    debug('Express server listening on port ' + server.address().port);
});

var io = require('socket.io').listen(server);

io.on('connection', require('../routes/socket.js'));

All my routes and other Express setup is in ../../server.js.

我的所有路线和其他Express设置都在../../server.js中。

var routes = require('./server/routes/index');
var user = require('./server/routes/user');
...

app.use('/', routes);
app.use('/api/user/', user);
...
app.use('*', routes);

Then in ../routes/socket.js, I've got this boilerplate:

然后在../routes/socket.js中,我有这个样板:

module.exports = function (socket) {
    socket.emit('send:news', { hello: 'world' });

    setInterval(function () {
        socket.emit('send:time', {
            time: (new Date()).toString()
        });
    }, 1000);

    return socket;
};

This is working beautifully, I might add. But now I want to be able to emit events from the various routes in my quite-ordinary Express app, and I can't for the life of me figure out the right way to get a reference to the socket object I need.

我可以补充说,这很漂亮。但是现在我希望能够在我非常普通的Express应用程序中从各种路径发出事件,而且我不能为我的生活找到正确的方法来获取对我需要的套接字对象的引用。

Example: when a user makes a comment, I'd like to emit an event to all connected users notifying them of the new comment. From my routes file (./server/routes/user.js), how can I get access to the object I need to emit events?

示例:当用户发表评论时,我想向所有连接的用户发出一个事件,通知他们新的评论。从我的路由文件(./server/routes/user.js),如何访问我需要发出事件的对象?

Here's a skeleton of the relevant bits from a route file:

这是路径文件中相关位的框架:

var express = require('express');
var router = express.Router();

router.post('/', function (req, res) {
  ...
});

module.exports = router;

The only place I can access it is in the ../routes/socket.js file, which is useless.

我可以访问它的唯一地方是../routes/socket.js文件,这是无用的。

All of the routes are set in a app.js before there's any io or socket object to pass in.

在有任何io或socket对象传入之前,所有路由都在app.js中设置。

Should I be able to require('socket.io') and use it somehow to emit to all connected sockets?

我是否应该能够('socket.io')并以某种方式使用它来发射到所有连接的套接字?

Is there a sensible way to store the connected sockets on ../routes/socket.js so it can be required and emitted to from other routes?

是否有一种合理的方法可以将连接的套接字存储在../routes/socket.js上,以便可以从其他路径中将其连接到需要的位置?

Can anyone steer me in the right direction?

任何人都可以引导我朝着正确的方向前进吗?

4 个解决方案

#1


13  

I was able to ultimately get things working using this example: https://github.com/expressjs/generator/issues/45#issuecomment-53719435

我最终能够使用这个例子来解决问题:https://github.com/expressjs/generator/issues/45#issuecomment-53719435

I created a new file called server/io.js:

我创建了一个名为server / io.js的新文件:

var io = require('socket.io')();

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

module.exports = io;

Then I updated server/bin/www to this:

然后我将server / bin / www更新为:

#!/usr/bin/env node
var debug = require('debug')('gokibitz');
var app = require('../../server');
var io = require('../io');

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
    debug('Express server listening on port ' + server.address().port);
});

io.attach(server);

Then, in my route, I use this:

然后,在我的路线中,我使用这个:

var io = require('../io');
...
io.emit(...);

The missing piece for me, at least, was the ability to create the io object separately, return the correct object, then use io.attach(server) inside bin/www to start it up at the right point.

对我来说,缺少的部分至少是能够单独创建io对象,返回正确的对象,然后在bin / www中使用io.attach(服务器)在正确的位置启动它。

Hopefully this will help someone else following in my footsteps.

希望这会帮助其他人追随我的脚步。

#2


3  

I think you are confused with the concepts. The socket.io lib uses or emulate a websocket (bidirectional socket) with the client, and have not relation with routes.

我认为你对这些概念感到困惑。 socket.io lib使用或模拟与客户端的websocket(双向套接字),并且与路由无关。

You can send a notification to all sockets using the io object:

您可以使用io对象向所有套接字发送通知:

io.emit('message_to_all', true);

You have to an array on io.sockets, with all sockets.

您必须在io.sockets上使用所有套接字的数组。

You can uses namespaces or rooms to, I recomend you learn the documentation:

您可以使用名称空间或房间,我建议您学习文档:

http://socket.io/docs/rooms-and-namespaces/#

Add something:

If you want to send a message to all people in the same route, you can join to a channel with the same name of the path.

如果要向同一路径中的所有人发送消息,则可以加入具有相同路径名称的通道。

For example, in the client:

例如,在客户端:

var socket = io(window.location.href); // Or route..

And the server:

和服务器:

var nsp = io.of('/the/specific/route');
nsp.on('connection', function(socket){
  // ...
});
nsp.emit('message_to_all_in_route', data);

About the last question editing:

关于编辑的最后一个问题:

You can send the io object in request or response object to routes, using the Express midleware API:

您可以使用Express midleware API将请求或响应对象中的io对象发送到路由:

For example:

#!/usr/bin/env node
var debug = require('debug')('gokibitz');
var app = require('../../server');

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
    debug('Express server listening on port ' + server.address().port);
});

var io = require('socket.io').listen(server);

app.use(function (req, res, next) {
  res.io = io;
  next();
});

io.on('connection', require('../routes/socket.js'));

And in the route:

并在路线:

route.post('/post/:id/comments', function (req, res) {

   // Do your logic

  var postio = res.io.of('/post/' + req.params.id);
  postio.emit('new_comment', commentData);

});

#3


1  

As I said in my comment, you can send to all connected clients with:

正如我在评论中所说,您可以通过以下方式向所有连接的客户发送:

io.emit(msg, data);

This will require access to the io object that you created in your first module. The usual way to share that with your module with your routes modeule would be to export a method from the routes module that lets you pass it the io object and then after you've required in the routes module and created the io object, you can just call that method to pass the io object to the routes module and it can save it locally for future use.

这将需要访问您在第一个模块中创建的io对象。通过路由模式与模块共享的常用方法是从routes模块导出一个方法,让你传递io对象,然后在routes模块中需要并创建io对象之后,你可以只需调用该方法将io对象传递给routes模块,它就可以将其保存在本地以备将来使用。

io is just a shared object like the app object is. If you want a module to be able to use a shared object, the usual way is that you call some method in that module to share with it some objects that it can then use.

io只是app对象的共享对象。如果您希望模块能够使用共享对象,通常的方法是在该模块中调用某个方法与其共享一些它可以使用的对象。

#4


0  

I have made a new file sockets.js in that file:

我在该文件中创建了一个新文件sockets.js:

var socketio = require('socket.io');
var io;

module.exports = {
socketServer: function (app) {
    io = socketio.listen(app);

    io.on('connection', function (socket) {

        console.log(Object.keys(users));
        socket.on('message', function (data) {
            io.emit('updateChat', 'Hello World!')
        });
    });
  }
}

And in my app.js:

在我的app.js中:

var express = require('express');
var app = express();
var http = require('http').createServer(app);
var port = process.env.PORT || 3000;

var io = require('./sockets').socketServer(http);
http.listen(port, function () {
    console.log('SERVER RUNNING.. PORT: ' + port)
});

This is working for me. Good Luck!

这对我有用。祝你好运!

#1


13  

I was able to ultimately get things working using this example: https://github.com/expressjs/generator/issues/45#issuecomment-53719435

我最终能够使用这个例子来解决问题:https://github.com/expressjs/generator/issues/45#issuecomment-53719435

I created a new file called server/io.js:

我创建了一个名为server / io.js的新文件:

var io = require('socket.io')();

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

module.exports = io;

Then I updated server/bin/www to this:

然后我将server / bin / www更新为:

#!/usr/bin/env node
var debug = require('debug')('gokibitz');
var app = require('../../server');
var io = require('../io');

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
    debug('Express server listening on port ' + server.address().port);
});

io.attach(server);

Then, in my route, I use this:

然后,在我的路线中,我使用这个:

var io = require('../io');
...
io.emit(...);

The missing piece for me, at least, was the ability to create the io object separately, return the correct object, then use io.attach(server) inside bin/www to start it up at the right point.

对我来说,缺少的部分至少是能够单独创建io对象,返回正确的对象,然后在bin / www中使用io.attach(服务器)在正确的位置启动它。

Hopefully this will help someone else following in my footsteps.

希望这会帮助其他人追随我的脚步。

#2


3  

I think you are confused with the concepts. The socket.io lib uses or emulate a websocket (bidirectional socket) with the client, and have not relation with routes.

我认为你对这些概念感到困惑。 socket.io lib使用或模拟与客户端的websocket(双向套接字),并且与路由无关。

You can send a notification to all sockets using the io object:

您可以使用io对象向所有套接字发送通知:

io.emit('message_to_all', true);

You have to an array on io.sockets, with all sockets.

您必须在io.sockets上使用所有套接字的数组。

You can uses namespaces or rooms to, I recomend you learn the documentation:

您可以使用名称空间或房间,我建议您学习文档:

http://socket.io/docs/rooms-and-namespaces/#

Add something:

If you want to send a message to all people in the same route, you can join to a channel with the same name of the path.

如果要向同一路径中的所有人发送消息,则可以加入具有相同路径名称的通道。

For example, in the client:

例如,在客户端:

var socket = io(window.location.href); // Or route..

And the server:

和服务器:

var nsp = io.of('/the/specific/route');
nsp.on('connection', function(socket){
  // ...
});
nsp.emit('message_to_all_in_route', data);

About the last question editing:

关于编辑的最后一个问题:

You can send the io object in request or response object to routes, using the Express midleware API:

您可以使用Express midleware API将请求或响应对象中的io对象发送到路由:

For example:

#!/usr/bin/env node
var debug = require('debug')('gokibitz');
var app = require('../../server');

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
    debug('Express server listening on port ' + server.address().port);
});

var io = require('socket.io').listen(server);

app.use(function (req, res, next) {
  res.io = io;
  next();
});

io.on('connection', require('../routes/socket.js'));

And in the route:

并在路线:

route.post('/post/:id/comments', function (req, res) {

   // Do your logic

  var postio = res.io.of('/post/' + req.params.id);
  postio.emit('new_comment', commentData);

});

#3


1  

As I said in my comment, you can send to all connected clients with:

正如我在评论中所说,您可以通过以下方式向所有连接的客户发送:

io.emit(msg, data);

This will require access to the io object that you created in your first module. The usual way to share that with your module with your routes modeule would be to export a method from the routes module that lets you pass it the io object and then after you've required in the routes module and created the io object, you can just call that method to pass the io object to the routes module and it can save it locally for future use.

这将需要访问您在第一个模块中创建的io对象。通过路由模式与模块共享的常用方法是从routes模块导出一个方法,让你传递io对象,然后在routes模块中需要并创建io对象之后,你可以只需调用该方法将io对象传递给routes模块,它就可以将其保存在本地以备将来使用。

io is just a shared object like the app object is. If you want a module to be able to use a shared object, the usual way is that you call some method in that module to share with it some objects that it can then use.

io只是app对象的共享对象。如果您希望模块能够使用共享对象,通常的方法是在该模块中调用某个方法与其共享一些它可以使用的对象。

#4


0  

I have made a new file sockets.js in that file:

我在该文件中创建了一个新文件sockets.js:

var socketio = require('socket.io');
var io;

module.exports = {
socketServer: function (app) {
    io = socketio.listen(app);

    io.on('connection', function (socket) {

        console.log(Object.keys(users));
        socket.on('message', function (data) {
            io.emit('updateChat', 'Hello World!')
        });
    });
  }
}

And in my app.js:

在我的app.js中:

var express = require('express');
var app = express();
var http = require('http').createServer(app);
var port = process.env.PORT || 3000;

var io = require('./sockets').socketServer(http);
http.listen(port, function () {
    console.log('SERVER RUNNING.. PORT: ' + port)
});

This is working for me. Good Luck!

这对我有用。祝你好运!