在其他模块中使用socket.io访问套接字发射器nodejs表示

时间:2018-02-06 00:46:48

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

我将通过说我一般都是nodejs的新手来说明这一点。来自C#的世界,这对我来说是一种完全不同的思维方式。 我已经完成了一些课程,我正在建立一个小网站作为对自己的测试。而且我失败了!

我正在使用带有节点的socket.io,而我正试图偶尔用发射器广播一条消息。我现在不关心特定的套接字点(虽然我将来会这样),所以这个发射器应该向所有人发送。

我无法从其他模块访问io对象。 我将发布我的server.js文件,以及app / index.js,socket / index.js,helpers / index.js和api / index.js。我希望发布这些内容将显示它应该如何工作。

理想情况下,为了保持一致性,我想将所有与套接字相关的项保留在套接字模块中。现在,我正在尝试在helpers模块中运行一个方法,但理想情况下套接字模块会更好。

无论如何,server.js:

'use strict';
const express = require('express');
const app = express();
const cryptometers = require('./app');
const api = require('./app/api');
const fs = require('fs');
const sources = require('./app/api/sources.json');

app.set('port', process.env.PORT || 3000);
app.set('view engine', 'ejs');

app.use(express.static('public'));
app.use(cryptometers.session);
app.use('/', cryptometers.router);

cryptometers.ioServer(app).listen(app.get('port'), () =>{
    console.log('app listening on port ' + app.get('port'));

api.getData(sources[0].source, sources[0].url, app);
setInterval(function(){api.getData(sources[0].source, sources[0].url, app)}, 60000);

});

标准票价。我刚刚添加了一个数据检索器,每分钟调用一次api,这会更新数据库。

应用程序/ index.js:

'use strict';

const config = require('./config');

// create an IO server instance
let ioServer = app => {
    app.locals.globalMarketCap = [];

    const server = require('http').Server(app);
    const io = require('socket.io')(server);
    io.set('transports', ['websocket']);

    io.use((socket, next) => {
        require('./session')(socket.request, {}, next);
    });
    require('./socket')(io,app);
    return server;
}


// turns router into a module
module.exports = {
    router: require('./routes')(),
    session: require('./session'),
    ioServer,

}

这里我正在初始化socket.io,将其绑定到应用程序。它也是我初始化本地存储数据阵列的地方。 (这是一个很好的地方吗?)

插座/ index.js:

'use strict';
const h = require('../helpers');

module.exports = (io, app) => {

    io.of('/').on('connection', socket =>{
        console.log('socket.io connected to client');

        if(app.locals.globalMarketCap){
            socket.emit('globalMarketCap', JSON.stringify(app.locals.globalMarketCap));
        }
    })
}

这里我正在响应连接事件,并推出我在上一个文件中定义的数据数组。同样,理想情况下,我希望所有套接字类型的东西留在这里。

助手/ index.js:

'use strict';
const router = require('express').Router();
const db = require('../db');

// iterate through the routes object and mount the routes
let _registerRoutes = (routes, method) => {
    for(let key in routes){
        if(typeof routes[key] === 'object' && routes[key] !== null && !(routes[key] instanceof Array)){
            _registerRoutes(routes[key], key);
        } else {
            // Register the routes
            if(method === 'get'){
                router.get(key, routes[key]);
            } else if(method === 'post'){
                router.post(key, routes[key]);
            } else {
                router.use(routes[key]);
            }
        }
    }
}

let route = routes => {
    _registerRoutes(routes);
    return router;
}

let updateGlobalMarketCap = (app) =>{
   //app.io.socket.emit('globalMarketCap', JSON.stringify(app.locals.globalMarketCap))
}

module.exports = {
    route,
    updateGlobalMarketCap
}

updateGlobalMarketCap注释掉的行就是我痛苦的地方。试图访问那里的io对象。

API / index.js

'use strict';

const axios = require("axios");
const db = require("../db");
const h = require("../helpers");

let getData = (source, url, app, cryptoMeters) => {
    axios
        .get(url)
        .then(response => {
            //console.log(response.data);
            response.data["source"] = source;
            var data = new db.globalMarketCapModel(response.data);
            app.locals.globalMarketCap = response.data;
            var query = { source: source};

            db.globalMarketCapModel.findOne({
                "source":source
            }, 'source old_total_market_cap_usd total_market_cap_usd', function(err, market) {
                if (market) {
                    if(market.old_total_market_cap_usd != response.data.total_market_cap_usd
                    && market.total_market_cap_usd != response.data.total_market_cap_usd){
                        response.data["old_total_market_cap_usd"] = market.total_market_cap_usd;
                        h.updateGlobalMarketCap(app);
                    }

                    db.globalMarketCapModel.update(query, response.data, function (err) {
                        if (err) {
                            console.log("uhoh")
                        } else {
                            return true;
                        }
                    });
                } else {
                    data.save(function (err) {
                        if (err) {
                            console.log("uhoh")
                        } else {
                            return true;
                        }
                    })
                }
            })

            return true;
        })
        .catch(error => {
            console.log(error);
            return false;
        });
}


module.exports = {
    getData

}

这里的getData函数是对更新发射器进行调用的地方。

我已经考虑过使用标准节点事件发射器作为我的问题的解决方案,但这可能会使工作变得简单,并且有一个更简单的答案。 无论如何,感谢阅读,我对迄今为止我写的任何评论感兴趣。陷阱,错误等。在这里学习! :)

1 个答案:

答案 0 :(得分:0)

有许多不同的方法来组织代码以完成io对象的共享。这是一个这样的计划。您将socket.io初始化代码分解为自己的模块。您为该模块提供了两个主要功能:

  1. 构造函数(您将服务器传递给它),允许socket.io在您的服务器上初始化自己。

  2. io实例初始化后获取io实例的方法。

  3. 这将允许项目中想要访问const io = require('./io.js').getIO(); 对象的任何其他代码执行以下操作:

    io

    以下是// io.js // singleton instance of socket.io that is stored here after the // constructor function is called let ioInstance; modules.exports = function(server) { const io = require('socket.io')(server); io.set('transports', ['websocket']); io.use((socket, next) => { require('./session')(socket.request, {}, next); }); // save in higher scope so it can be obtained later ioInstance = io; return io; } // this getIO method is designed for subsequent // sharing of the io instance with other modules once the module has been initialized // other modules can do: let io = require("./io.js").getIO(); module.exports.getIO() { if (!ioInstance) { throw new Error("Must call module constructor function before you can get the IO instance"); } return ioInstance; } 模块的结构:

    const io = require('./io.js')(server);
    

    并且,此模块将初始化为:

    .getIO()

    您将Web服务器传递给它,以便它可以挂钩。必须先将其初始化,然后才能对其使用ioInstanceioInstance模块中的存储使用模块缓存。模块初始化代码只运行一次。之后,每次只返回相同的导出,可以访问模块中保存的'Datasources' => [ 'default' => [ 'className' => 'Cake\Database\Connection', 'driver' => 'Cake\Database\Driver\Mysql', 'persistent' => false, 'host' => 'localhost', 'username' => 'root', 'password' => 'root', 'database' => 'vom', 'encoding' => 'utf8', 'timezone' => 'UTC', 'flags' => [], 'cacheMetadata' => true, 'log' => false, ... ... ...