Socket.io - 在 node.js 的单独文件中监听事件

Posted

技术标签:

【中文标题】Socket.io - 在 node.js 的单独文件中监听事件【英文标题】:Socket.io - listen events in separate files in node.js 【发布时间】:2014-07-02 10:44:15 【问题描述】:

例如我的想法是:

文件1.js

 io.sockets.on('connection', function (socket) 
      socket.on('file1Event', function () 
           //logic
      );
 );

文件2.js

 io.sockets.on('connection', function (socket) 
      socket.on('file2Event', function () 
           //logic
      );
 );

这段代码是用于节点服务器的,这段代码我会遇到问题吗?

【问题讨论】:

【参考方案1】:

不,只需使用相同的“io”对象。

文件1.js

exports = module.exports = function(io)
  io.sockets.on('connection', function (socket) 
    socket.on('file1Event', function () 
      console.log('file1Event triggered');
    );
  );

文件2.js

exports = module.exports = function(io)
  io.sockets.on('connection', function (socket) 
    socket.on('file2Event', function () 
      console.log('file2Event triggered');
    );
  );

app.js

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')
  , file1 = require('./File1')(io)
  , file2 = require('./File2')(io)

app.listen(3000);

function handler (req, res) 
  fs.readFile(__dirname + '/index.html',
  function (err, data) 
    if (err) 
      res.writeHead(500);
      return res.end('Error loading index.html');
    

    res.writeHead(200);
    res.end(data);
  );

index.html

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.emit('file1Event');  // 'file1Event triggered' will be shown
  socket.emit('file2Event');  // 'file2Event triggered' will be shown
</script>

【讨论】:

【参考方案2】:

注意不要为每个文件生成新的连接事件。您应该使用相同的 on('connection') 事件,否则在导入 10 个文件后,您将从节点收到此错误:MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 connection listeners added. Use emitter.setMaxListeners() to increase limit

更好的方法是在你的主文件中这样做:

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

  require('pathToSocketRoutesFile1')(socket);
  require('pathToSocketRoutesFile2')(socket);

  require('pathToSocketRoutesFileN')(socket);

  return io;

;

在每个单独的文件中:

module.exports = function(socket) 

  socket.on('eventName1', function() 
    //...
  );

  socket.on('eventName2', function() 
    //...
  );

;

【讨论】:

如果您还需要在函数中使用io,请不要忘记将它与socket 一起传递,如下所示:require('pathToSocketRoutesFileN')(socket, io)。另外你不需要在连接函数中返回io 太棒了!有没有办法使用特定于文件的中间件?就像一个只能在文件 pathToSocketRoutesFile1 上运行的中间件?【参考方案3】:

另一种选择是创建一个 rootSocket,它处理初始连接,然后将套接字传递给其他处理程序。

const rootSocket = (io) => 
    io.sockets.on('connection', (socket) => 
        authorization(socket);
        chat(socket);
    );
;
exports.default = rootSocket;

【讨论】:

【参考方案4】:

您可以在任何路由中使用 IO 模块,只需创建全局中间件。

socketiomw.js

 module.exports = (io)=>
      return (req,res,next)=>
        req.io = io;
        next();
      
  

middlewares.js

module.exports.global = 
  socketIo:require('./socketiomw'),
  // add other global middleware
;

index.js

const express = require('express');
const app = express();
const port = 3000;
const http = require('http');
const server = http.createServer(app);
const  Server  = require("socket.io");
const io = new Server(server);  
//global middleware initialization
app.use(require('./middlewares').global.socketIo(io));

app.get('/notify',(req,res)=> 
   req.io.emit("hello");
   req.io.to("someRoom").emit("some event");
   req.io.to("room1").to("room2").to("room3").emit("some event");
   req.io.of("/").adapter.on("create-room", (room) =>  
       console.log(`room $room was created`);
   );
   req.io.of("/").adapter.on("join-room", (room, id) =>   
      console.log(`socket $id has joined room $room`);
   );
   req.json( success:true ) 
);

server.listen(port, () => 
  console.log(`Example app listening at http://localhost:$port`)
)

我在全局中间件中使用了这个,所以我可以在任何路由中使用这个io module

【讨论】:

我现在如何使用 Io 模块?我应该在我想使用它的文件中放入什么? 我更新了答案。 ` app.get('/notify',(req,res)=> req.io.emit("hello"); req.json( success:true ) ); `【参考方案5】:

rootSocket.js:

const rootSocket = (io) => 
    io.on('connection', (socket) => 
        console.log('New connection');
          // possibility to outsource events
         socket.on('myEvent', () => 
           console.log('myEvent triggered');
         );
    );

module.exports = rootSocket;

index.js:

const express = require('express');
const app = express();
//app.use(express.json());
//const cors = require('cors');
//app.use(cors());

const http = require('http');
const server = http.createServer(app);

const socketIo = require('socket.io');
const io = socketIo(server);
const rootSocket = require('./rootSocket')(io);

const port = 8000;
// process.env.PORT for production
server.listen(port, () => console.log('server started on ' + port));

【讨论】:

以上是关于Socket.io - 在 node.js 的单独文件中监听事件的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 和 socket.io 的混淆

找不到Node.js /socket.io/socket.io.js express 4.0

node.js + socket.io:拍卖网站开发

Node.js + Socket.io 在套接字中存储数据

Node.js - Socket.io:socket.request 未定义

通过 Socket.IO 的 WebSocket 设计模式