【问题标题】:Socket.io - listen events in separate files in node.jsSocket.io - 在 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
      });
 });

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

【问题讨论】:

    标签: javascript node.js events socket.io


    【解决方案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));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-24
          • 2018-01-26
          相关资源
          最近更新 更多