在 Node 和 Express 中分离套接字 IO 调用以获得更清晰的代码

Separating socket IO calls for cleaner code in Node and Express

所以,我正在制作一个应用程序,我已经让套接字 IO 正常工作,并且该应用程序仅在 Express 上运行。

无论如何,在主服务器文件中是我进行调用的地方。一些例子:

//Object 1
io.of('/type1').on
(   'connection', socket => 
{   socket.on
    (   'call1', () =>
        {   doSomething1();
        }
    );
}
);

// Object 2
io.of('/type2').on
(   'connection', socket => 
{   socket.on
    (   'call2', () =>
        {   doSomething2();
        }
    );
}
);

显然,有更多 socket.on 调用各种对象。我想做的实际上是将这些对象的逻辑从主循环中分离到一些单独的文件中,以更好地清理我拥有的主 server.js 文件。我有大约 300 行各种套接字调用。

对象 1 等 socketCalls1.js 等

唯一的问题是 io 变量似乎不能跨多个文件共享...有没有好的、干净的方法来做到这一点?

The only thing is that the io variable doesn't seem sharable across multiple files...

这不是真的。您可以像任何其他变量一样将 io 变量传递到函数和模块外。也像任何其他变量一样,它会自动将范围限定为单个文件。

有多种方法可以跨文件共享对象,如果您已经了解了这一点,我相信您已经使用了其中的大部分方法。只是也许你还没有意识到自己在做什么。

方法 1:将 io 传递给函数。

拆分逻辑的一种方法是将其拆分到多个模块中。由于您可以将对象传递给函数,因此您的模块应该导出函数。例如:

  • 文件 1:type1.js

    function init (io) {
      io.of('/type1').on
      (   'connection', socket => 
      {   socket.on
          (   'call1', () =>
              {   doSomething1();
              }
          );
      }
      );
    }
    
    module.exports = init;
    
  • 文件 2:type2.js

    function init (io) {
      io.of('/type2').on
      (   'connection', socket => 
      {   socket.on
          (   'call2', () =>
              {   doSomething2();
              }
          );
      }
      );
    }
    
    module.exports = init;
    
  • main.js

    const type1 = require('./path/to/type1.js');
    const type2 = require('./path/to/type2.js');
    
    // some code to init your app ...
    
    type1.init(io); // pass io to type1 module
    type2.init(io); // pass io to type2 module
    

之所以有效,是因为 io 只是一个常规变量。就像任何变量一样,您可以将其作为函数参数传递。没什么特别的,这都是编程语言的基本特征。

方法 2:作为模块共享 io

另一种技术特定于模块在 node.js 中的工作方式。模块是节点中的单例。这意味着一个模块只代表一个对象。如果 3 个不同的文件 require() 是模块,它们都将获得相同的对象。

我们可以使用它在模块之间共享 io 对象:

  • file1: 服务器-init.js

    let app = require('express')();
    let http = require('http').Server(app);
    let io = require('socket.io')(http);
    
    module.exports = {
        app: app,
        http: http,
        io: io
    }
    
  • 文件 2:type1.js

    const io = require('./path/to/server-init').io;
    // Alternatively you can use the syntax:
    // const { io } = require('./path/to/server-init');
    
    function init () {
      io.of('/type1').on
      (   'connection', socket => 
      {   socket.on
          (   'call1', () =>
              {   doSomething1();
              }
          );
      }
      );
    }
    
    module.exports = init;
    
  • 文件 3:type2.js

    const io = require('./path/to/server-init').io;
    
    function init () {
      io.of('/type2').on
      (   'connection', socket => 
      {   socket.on
          (   'call2', () =>
              {   doSomething2();
              }
          );
      }
      );
    }
    
    module.exports = init;
    
  • main.js

    const type1 = require('./path/to/type1.js');
    const type2 = require('./path/to/type2.js');
    const { http, app } = require('./path/to/server-init');
    
    // some init code
    
    type1.init();
    type2.init();
    http.listen(PORT);