提问者:小点点

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


首先,我要说我对nodejs一般都不熟悉。来自C#的世界,这对我来说是一种完全不同的思维方式。我已经学习了一些课程,我正在建立一个小网站,作为对自己的一种测试。我要失败了!

我将socket.io与node一起使用,并尝试偶尔用发射器广播一条消息。我不关心具体的插座点现在(虽然我会在未来),所以这一发射器应该出去给每个人。

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

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

总之,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,从而更新数据库。

app/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,将其绑定到应用程序。这也是我初始化本地数据存储阵列的地方。(这里是做这件事的好地方吗??)

socket/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));
        }
    })
}

这里我响应连接事件,并推出我在上面最后一个文件中定义的数据数组。再次强调,理想情况下,我希望所有的套接字类型的东西都留在这里。

helpers/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个答案

匿名用户

有许多不同的方法来组织代码以实现IO对象的共享。这里有一个这样的方案。您将socket.io初始化代码拆分为它自己的模块。您为该模块提供了两个主要特性:

>

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

    IO实例初始化后获取该实例的方法。

    这将允许项目中希望访问IO对象的任何其他代码执行如下操作:

    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);
    

    将它传递给web服务器,这样它就可以挂接到web服务器上。在任何人可以在它上使用.getio()之前,它必须像这样初始化。IOInstance模块中的存储利用了模块缓存。模块初始化代码只运行一次。之后,每次返回相同的导出,这些导出可以访问模块中保存的IOInstance