我将通过说我一般都是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函数是对更新发射器进行调用的地方。
我已经考虑过使用标准节点事件发射器作为我的问题的解决方案,但这可能会使工作变得简单,并且有一个更简单的答案。 无论如何,感谢阅读,我对迄今为止我写的任何评论感兴趣。陷阱,错误等。在这里学习! :)
答案 0 :(得分:0)
有许多不同的方法来组织代码以完成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);
并且,此模块将初始化为:
.getIO()
您将Web服务器传递给它,以便它可以挂钩。必须先将其初始化,然后才能对其使用ioInstance
。 ioInstance
模块中的存储使用模块缓存。模块初始化代码只运行一次。之后,每次只返回相同的导出,可以访问模块中保存的'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,
... ... ...
。