以下是我的node.js应用程序中的server.js文件。我希望我的服务器上的其他文件可以访问我的socket.io实例,以便从我的API (listingRoutesApi, userRoutesApi etc.) (refer to code)
发出事件。
我的问题是在创建服务器之前就声明了路由;但是,socket.io实例是在创建服务器后创建的。
我使用的解决方案是声明一个全局io
变量,该变量将使我能够从Web应用程序中的任何位置发出事件,例如:
global.io.of('/analytics').to(listing._id).emit('message', "There was a post.");
我的问题是:这样做是否有任何陷阱/危险,并且从长期来看,我会遇到任何可扩展性问题吗?此外,还有更好的方法可以实现我的目标吗?
server.js文件中的代码:
const app = express();
app.use('/api', listingRoutesApi);
app.use('/api', userRoutesApi);
app.use('/api', imageRoutesApi);
// ...plenty more endpoints here...
app.use(serveStatic(path.join(__dirname, "/dist")));
app.use(history());
app.use(serveStatic(path.join(__dirname, "/dist")));
const server = app.listen(port, () => { console.log('server started ' + port); });
/* Start socket. */
global.io = socketio(server);
const analytics = global.io.of("/analytics");
analytics.on('connection', (socket) => {
socket.on('join', (data) => {
socket.join(data.room);
analytics.in(data.room).emit('message', `New user joined ${data.room}`);
});
socket.on('leave', (data) => {
analytics.in(data.room).emit('message', `User leaving ${data.room}`);
socket.leave(data.room);
});
socket.on('disconnect', () => {
console.log('user disconnected');
});
});
我之所以问这个问题,是因为this SO post通过声明一个getIOInstance
函数并将其传递给需要它的所有模块来回答类似的问题。虽然它可以正常工作,但感觉并不优雅,并且由于我希望在我的应用程序中只拥有一个完全相同的socket.io实例,因此显得有些不必要。
此外,我认为我面临的挑战是非常普遍的挑战。但是,我无法找到许多解决方案来解决这个问题,而没有一个建议使用全局变量。
答案 0 :(得分:2)
Node.js是模块化环境。假定模块可以解决全局变量所具有的一些缺陷。
如果只需要一个实例,则模块自然会提供单例实例:
app.js
module.export = express();
server.js
const app = require('./app');
module.export = app.listen(...);
socketio.js
const server = require('./server');
module.export = socketio(server);
index.js
const app = require('./app');
const io = require('./socketio');
...
Express还为应用程序全局依赖项application settings table提供了一个容器。它可以在可用的应用程序实例的任何地方使用,例如作为中间件中的req.app.get(...)
。如果也是单例,那么在中间件外部访问Express应用程序实例也不会成为问题:
app.js
module.export = express();
index.js
const app = require('./app');
...
const server = app.listen(...);
const io = socketio(server);
app.set('io', io);
// available as req.app.get('io') inside middlewares
// and as require('./app).get('io') outside them