在快速路由文件中使用socket.io

时间:2013-09-17 17:28:28

标签: node.js sockets socket.io

我正在尝试将Socket.io与Node.js一起使用并发送到路由逻辑中的套接字。

我有一个相当标准的Express 3设置,其中包含一个位于路由中的server.js文件,然后我有一个index.js,它位于路径文件夹中,用于导出站点的所有页面/可公开访问的功能。所以他们看起来像:

exports.index = function (req, res) {
    res.render('index', {
        title: "Awesome page"
    });
}; 

使用server.js中定义的路由,如:

app.get('/',routes.index);

我假设我必须在server.js中创建socket.io对象,因为它需要服务器对象,但是如何访问该对象并从index.js导出函数向它发出?

6 个答案:

答案 0 :(得分:66)

现在有一种更好的方法可以使用Express 4.0。

您可以使用app.set()存储对io对象的引用。

基本配置:

var app = require('express')();
var server = app.listen(process.env.PORT || 3000);
var io = require('socket.io')(server);
// next line is the money
app.set('socketio', io);

内部路线或中间件:

exports.foo = function(req,res){
    // now use socket.io in your routes file
    var io = req.app.get('socketio');
    io.emit('hi!');
}

有关app.set()app.get()的信息如下:

  

app.set(名称,值)

     

将设置名称指定给值。您可以存储任何您想要的值,   但某些名称可用于配置服务器的行为。   这些特殊名称列在app settings table

中      

调用app.set('foo', true)获取布尔属性与   致电app.enable('foo')。同样,呼叫app.set('foo', false)   对于布尔属性,与调用app.disable('foo')相同。

     

使用app.get()检索设置的值。

来源:https://expressjs.com/en/api.html#app.set

答案 1 :(得分:14)

您可以将路径文件设置为函数,并在需要文件时传递Socket.IO对象。

module.exports = function(io) {
  var routes = {};
  routes.index = function (req, res) {
    io.sockets.emit('payload');
    res.render('index', {
      title: "Awesome page"
    });
  };
  return routes;
};

然后需要这样的路线:

var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var routes = require('./routes')(io);

答案 2 :(得分:8)

aarosil的答案很棒,但我遇到了与Victor一样的问题,使用这种方法管理客户端连接。对于客户端上的每次重新加载,您将在服务器上获得尽可能多的重复消息(第二次重新加载= 2次重复,第三次= 3次重复等)。

扩展了aarosil的答案,我使用这种方法在我的路由文件中使用套接字对象,并管理连接/控制重复消息:

内部服务器文件

// same as aarosil (LIFESAVER)
const app = require('express')();
const server = app.listen(process.env.PORT || 3000);
const io = require('socket.io')(server);
// next line is the money
app.set('socketio', io);

内部路线文件

exports.foo = (req,res) => {

   let socket_id = [];
   const io = req.app.get('socketio');

   io.on('connection', socket => {
      socket_id.push(socket.id);
      if (socket_id[0] === socket.id) {
        // remove the connection listener for any subsequent 
        // connections with the same ID
        io.removeAllListeners('connection'); 
      }

      socket.on('hello message', msg => {
        console.log('just got: ', msg);
        socket.emit('chat message', 'hi from server');

      })

   });
}

答案 3 :(得分:3)

使用

有什么不对
global.io = require('socket.io').listen(server);

答案 4 :(得分:1)

这里超级晚了,但是我想访问我的路由中的套接字,特别想在保存到数据库后广播消息。我使用@aarosil提供的答案来设置/获取io对象,向每个客户端发送其连接时的套接字ID,然后在路由中使用套接字ID以便能够使用socket.broadcast.emit()而不是{{1} }。

在服务器中:

io.emit()

我随每个请求发送套接字ID,然后可以在路由中执行以下操作:

const io = require('socket.io')(server)
app.set('socketio', io)

io.on('connect', socket => {
  socket.emit('id', socket.id) // send each client their socket id
})

答案 5 :(得分:0)

如果您在父模块中导出服务器,

module.parent.exports.server也会有效。