跨server.js和api的Socket.io调用

时间:2019-07-27 12:07:30

标签: javascript node.js socket.io

我正在尝试使用socket.io从两个文件发出:server.js/routes/api.game.js

我的server.js

...
const server = require('./middleware/socket').server;
const io = require('./middleware/socket').io;

io.on('connection', (socket) => {
  socket.on("startGame", () => {
    io.emit('gameStarted')
  });
});

这可以正确显示

我的/middleware/socket.js

const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const http = require('http');
const cors = require("cors");
const path = require('path');
const server = http.createServer(app);
const io = require('socket.io')(server);

const games = require("../routes/api/games");

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.use(cors());

app.use("/api/games", games);
app.use('/public', express.static(path.join(__dirname, '/public')));

app.get('/', (req, res) => {
  res.send("IT'S WORKING!")
})

module.exports = { io: io, app: app, server: server };

还有我的/routes/api/game.js

const server = require('../../middleware/socket').server;
const io = require('../../middleware/socket').io;

router.get("/start/:handle", (req, res) => {
  io.emit('nextquestion')
})

module.exports = router;

但是这里发出显示错误 TypeError:无法读取未定义的属性'emit'

如何调用game.js文件中的发射?

1 个答案:

答案 0 :(得分:1)

您可以看到您具有循环依赖项:

  • socket.js需要game.js
  • game.js要求socket.js尚未初始化,因此该对象等于空对象

作为最佳实践,我建议不要在函数外部初始化对象,因为这就像在调用require时产生副作用。 game.js仅需要socket.io,因此,如果您拆分socket.js,则可以轻松摆脱循环依赖。

一个解决方案可以是socket.io的包装:

const socketIO = require('socket.io');

const self = module.exports = {
  io: {},
  start: server => {
    self.io = socketIO(server)
  }
};

启动后,请确保io已初始化。