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

How can I emit events to connected sockets using socket.io from within my Express 4 routes?

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

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

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'));

我所有的路线和其他 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);

然后在 ../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;
};

这工作得很好,我可以补充一下。但是现在我希望能够在我非常普通的 Express 应用程序中从各种路由发出事件,但我终其一生都无法找出正确的方法来获取对我需要的套接字对象的引用。

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

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

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

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

module.exports = router;

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

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

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

有没有一种合理的方法来存储 ../routes/socket.js 上连接的套接字,以便它可以被其他路由要求和发送?

谁能指引我正确的方向?

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

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

io.emit('message_to_all', true);

您必须在 io.sockets 上创建一个包含所有插槽的数组。

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

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

添加内容:

如果你想给同一路径的所有人发消息,你可以加入路径同名的频道。

例如在客户端:

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

和服务器:

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

关于最后一题编辑:

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

例如:

#!/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'));

并且在路线中:

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);

});

正如我在评论中所说,您可以发送给所有连接的客户端:

io.emit(msg, data);

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

io 只是一个共享对象,就像 app 对象一样。如果你想让一个模块能够使用一个共享对象,通常的方法是你在那个模块中调用一些方法来与它共享一些它可以使用的对象。

我最终能够使用这个示例让事情正常进行: https://github.com/expressjs/generator/issues/45#issuecomment-53719435

我创建了一个名为 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;

然后我将 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);

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

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

至少对我来说,缺少的部分是能够单独创建 io 对象,return 正确的对象,然后在 bin/www 中使用 io.attach(server)在正确的时间启动它。

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

我在该文件中创建了一个新文件 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!')
        });
    });
  }
}

在我的 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)
});

这对我有用。祝你好运!