首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建可重用的Socket.IO模块

如何创建可重用的Socket.IO模块
EN

Stack Overflow用户
提问于 2016-05-17 04:41:59
回答 4查看 3.4K关注 0票数 8

我在为我的Socket.IO库创建一个公开功能的模块时遇到了麻烦:

代码语言:javascript
复制
const sio = require('socket.io');
module.exports = function(server) {
  const io = sio(server);
  return {
    register: function(namespace) {
      let nsp = io.of(namespace);
      nsp.on('connect', function(socket) {
        // ...
      }
    }
  }
}

现在的问题是,我如何在其他模块中使用它?在我的app.js

我用Express创建了server,可以用require('./mysocketio')(server)实例化模块,但不能在其他模块中实例化,因为服务器在其他模块中不可用。解决这些循环依赖的好方法是什么?

EN

回答 4

Stack Overflow用户

发布于 2016-05-27 15:31:08

你可以通过不同的方式来实现这些,比如:

  • 将对象设置为全局命名空间。(更改全局需要注意)
  • 使用module.exports并需要其他文件中的对象。(如果处理不当,可能会导致循环依赖问题)
  • 将实例作为参数传递给控制器,而在路由中需要它们。

myModule.js模块,显示Socket.IO库的功能

代码语言:javascript
复制
const sio = require('socket.io');
module.exports = function(server) {
  const io = sio(server);
  return {
    register: function(namespace) {
      let nsp = io.of(namespace);
      nsp.on('connect', function(socket) {
        // ...
      }
    }
  }
}

FLow 1:设置全局命名空间中的模块。

app.js

代码语言:javascript
复制
var app = require('express').createServer();
var io = require('./myModule')(app);
global._io = io;

app.listen(80)

controller.js

代码语言:javascript
复制
module.exports = function(io){
    var that={};
    /*
     * Private local variable
     * made const so that 
     * one does not alter it by mistake
     * later on.
     */
    const _io = global._io; 

    that.myAction = function(req,res){

        _io.register('newRoom');
        res.send('Done');   
    }
    return that;
}

流2:将模块作为参数传递。

app.js

代码语言:javascript
复制
var app = require('express').createServer();
var io = require('./myModule')(app);

require(./router.js)(app,io);

app.listen(80);

router.js

代码语言:javascript
复制
/*
 * Contains the routing logic
 */
module.exports = function (app,io) {
//passing while creating the instance of controller for the first time.
var controller = require("./controller")(io);

app.get('/test/about',controller.myAction);
};

controller.js

代码语言:javascript
复制
module.exports = function(io){
    var that={};

    const _io = io; 

    that.myAction = function(req,res){

        _io.register('newsRoom');
        res.send('Done');   
    }

    // everything attached to that will be exposed
    // more like making public member functions and properties.
    return that;
}

全局流3:将io设置为。因此,不需要每次都通过服务器。

app.js

代码语言:javascript
复制
var app = require('express').createServer();
require('./myModule')(app);

require(./router.js)(app);

app.listen(80);

controller.js

代码语言:javascript
复制
// no need to pass the server as io is already initialized
const _io = require('./myModule')();

module.exports = function(io){
    var that={};

    that.myAction = function(req,res){

        _io.register('newsRoom');
        res.send('Done');   
    }
    return that;
}

myModule.js

代码语言:javascript
复制
module.exports = function( server ) {

  const _io = global._io || require('socket.io')(server);

  if(global._io === undefined){
    //initializing io for future use
    global._io = _io;
  }

  return {
    register: function(namespace) {
      let nsp = _io.of(namespace);
      nsp.on('connect', function(socket) {
        // ...
      }
    }
  }
}

可能,最干净的方法是将参数作为参数传递给控制器,而在路由中需要它们。虽然第三个流程看起来很有希望,但在更改全局名称空间时应该非常小心。

票数 5
EN

Stack Overflow用户

发布于 2016-05-20 18:11:00

这并不是真正的循环依赖;只是你的模块a)依赖于另一个不是全局可用的模块,b)你的模块可能在代码中的很多地方被使用了。

全局

一种可能的解决方案(有缺点)是,只加载一次模块,并将其附加到全局:global.mysocketio = require('./mysocketio')(server);

这允许您在加载项目后,在项目中的任何位置访问global.mysocketio。这是我个人用于自己的记录器构造的构造;我的记录器在代码周围的许多地方使用,所以我只是将其附加到global.log。

然而,全局变量的使用有点脏;它带来了名称空间分离的问题(某些代码决定使用global.mysocketio本身),并且它创建了一个“看不见”的依赖关系;其他代码只是假设某个全局变量将存在,并且不容易找到这些依赖关系。

导出

更好的解决方案是在需要的地方传递变量。有很多方法可以做到这一点。我知道您的app.js没有可用的服务器变量,但它肯定以某种方式包含了您的快速代码。如果您需要app.js提供的'server‘或'mysocketio’,只需从创建'server‘的模块中导出它即可。像这样:

module.exports.expressServerVar = server;

这只是我的2点意见;你是强烈反对我的观点,还是我错过了什么重要的东西?让我知道!

票数 2
EN

Stack Overflow用户

发布于 2016-05-20 18:40:56

我会使用工厂或依赖注入。你可以使用像jimple这样的东西。

但这里有一个不使用任何外部依赖项的示例。这绝对不是最好的代码示例,但希望它能让人明白这一点。我仍然推荐使用jimple而不是这个。

代码语言:javascript
复制
// app.js

var express = require('express');
var app = express();

var factory = require('./factory.js');
factory.setExpress(app); // This could also be done in the factory constructor. Or you could instanciate your express app in the factory.js class.


// factory.js
var socketIoModule = require('./your-socket-io-module.js')

function Factory() {

}

Factory.prototype.setExpress = function(app) {
    this.app = app;
}

Factory.prototype.getSocketIOModule = function() {
    return socketIoModule(this.app);
}

// By exporting it this way we are making it a singleton
// This means that each module that requires this file will
// get the same instance of factory.
module.exports = new Factory();


// some code that needs socket io module
var factory = require('./factory.js');

function() {
    var socketIo = factory.getSocketIOModule();

    socketIo.doStuff();
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37262923

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档