Как я могу излучать события в подключенные сокеты с помощью socket.io из моих экспресс-маршрутов 4?

это вопрос, который задали другие люди, но я не могу извлечь выгоду из ответов, которые им дали, из-за другой экспресс-настройки, которую я имею.

у меня есть розетка.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'));

все мои маршруты и другие Экспресс-установки в ../../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 прежде чем есть какой-либо объект ввода-вывода или сокета для передачи.

должен ли я быть в состоянии require('socket.io') и использовать его как-то выделяют на все подключенные сокеты?

есть ли разумный способ сохранить подключенное розетки на ../routes/socket.js так его можно требовать и испускать к от других маршрутов?

кто-нибудь может направить меня в правильном направлении?

4 ответов


я смог в конечном итоге заставить вещи работать, используя этот пример: 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 объект отдельно, верните правильный объект, затем используйте io.attach(server) внутри bin/www чтобы запустить его в нужной точке.

надеюсь, это поможет кому-то еще следовать по моим стопам.


Я думаю, что вы запутались с понятиями. Розетка.IO lib использует или эмулирует websocket (двунаправленный сокет) с клиентом и не имеет отношения к маршрутам.

вы можете отправить уведомление всем сокетам, используя объект ввода-вывода:

io.emit('message_to_all', true);

вы должны массив на io.розетки, со всеми розетками.

вы можете использовать пространства имен или комнаты, я рекомендую вам узнать документация:

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

о последнем вопросе редактирования:

вы можете отправить объект ввода-вывода в запрос или ответ объекта на маршруты, используя API Express midleware:

например:

#!/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 объект, созданный в первом модуле. Обычным способом поделиться этим с вашим модулем с вашим modeule маршрутов было бы экспортировать метод из модуля routes, который позволяет вам передать его io объект, а затем после того как Вы необходимые в routes модуль и создал


Я сделал новый файл 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)
});

это работает для меня. Удачи!