在多个模块中需要(相同的实例)socket.io

时间:2017-04-05 13:12:52

标签: javascript node.js sockets module socket.io

我有点困惑,关于如何在Node.js中要求和使用模块。

我的方案如下:

我在一个文件中编写了一个完整的服务器,它使用Socket.io进行实时通信。

现在index.js变得非常大了,我想将代码分成几个模块,以使其更易于管理。

例如,我有一些功能可以为客户提供调查,并回复他们的答案。我将所有这些函数放在一个单独的模块中,并在index.js中要求它。到目前为止工作正常。

我唯一关心的是,如果有另一种方法在模块中使用SAME套接字实例。

我目前的编码如下:

index.js:

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

io.on('connection', function (client) {
    client.on('getCurrentQuestion', function (data) {
        Survey.getCurrentQuestion(parseInt(data.survey_id), client.id);
    });
});

server.listen(port, server_url, function () {
    Survey.init(io);
});

survey.js:

var io = null;

var Survey = {};

Survey.init = function(socketio) {
    io = socketio;
};

Survey.getCurrentQuestion = function(survey_id, socket_id) {
    var response = {
        status: "unknown",
        survey_id: survey_id
    };

    // [...] some code that processes everything

    // then uses Socket.io to push something back to the client
    io.sockets.in(socket_id).emit('getCurrentQuestion', response);
};

module.exports = Survey;

这种方式有效,但我很高兴将init函数中的io传递给所需的模块。

这样做的“正确方法”是什么?

如果我在调查模块中require('socket.io'),它是否与index.js中的实例相同?

我怎么会要求,因为它需要server,这需要app中创建的index.js

我很困惑,希望有人可以帮助我。谢谢!

2 个答案:

答案 0 :(得分:1)

导入node.JS库时,您还可以传入对象。在您的情况下,index.js文件应更改为以下内容:

//index.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var Survey = require('./survey')(io);

然后只需更改您的survey.js代码即可获取io对象:

//survey.js

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

    Survey.getCurrentQuestion = function(survey_id, socket_id) {
        var response = {
            status: "unknown",
            survey_id: survey_id
        };

        // [...] some code that processes everything

        // then uses Socket.io to push something back to the client
        io.sockets.in(socket_id).emit('getCurrentQuestion', response);
    };

    return Survey;
};

要回答您的其他问题:

如果你在调查模块中require('socket.io'),它将是与index.js不同的实例。

修改

如果你想要一种更现代的方式...你可以使用ES6格式并创建一个类来更好地做到这一点:

'ES6 index.js

import SurveyClass from './Survey';
import * as express from 'express';
let app = express();
let server = require('http').createServer(app);
let io = require('socket.io')(server);
let MySurveyClass= SurveyClass(io);
let myInstance = new MySurveyClass();

myInstance.getCurrentQuestion(5, "some-socket-id");

'ES6 survey.js
export default class Survey{

    constructor(io){
        this.io= io;
    };


    getCurrentQuestion(survey_id, socket_id) {
        var response = {
            status: "unknown",
            survey_id: survey_id
        };

        // [...] some code that processes everything

        // then uses Socket.io to push something back to the client
        this.io.sockets.in(socket_id).emit('getCurrentQuestion', response);
    };




}

答案 1 :(得分:0)

在多个模块中执行此操作时:

var socketio = require('socket.io');

然后它将是所有要求的相同对象。

但如果你这样做:

var io = require('socket.io')(server);

即使两个地方的server中都有相同的对象,io也会是一个不同的值,因为它来自require('socket.io')返回的函数的不同调用,即使这些功能是一样的。

如果您想确保io相同,那么您可以做到,例如类似这样的事情:创建一个导出io承诺的模块以及一些初始化它的方法 - 一个获取server和所需一切的函数。现在,在您拥有server的地方,您可以要求模块并使用该导出的函数对其进行初始化,在其他地方您可以导入模块并使用承诺。

而不是承诺你可以使用回调甚至只是导出对象上的一个属性,这个属性最初可能是未定义的,并且在初始化socket.io时被定义但使用promise可能是最简单的解决方案,以确保你和#39;在尚未准备就绪的情况下不再使用它。

在你的问题中你没有提到你是否使用某个框架以及哪个框架(如果有的话),但是像Hapi这样的一些框架为你提供了一种简单的方法来共享这样的功能。例如。见:

如果您使用Hapi,那么您应该使用插件。如果其他框架然后搜索类似的功能。