首页 > 解决方案 > NodeJS,SocketIO IO发出功能不起作用

问题描述

tldr:SocketIO io 功能不起作用。

所以我正在开发一个使用 websockets 的游戏/网站,这样玩家就可以在解决一些问题时相互竞争。

我目前在一个文件中有与 socketIO 相关的代码,以便更容易设置测试,“webserver.js”如下所示:

const socketIO = require('socket.io');
const {
  addPlayerToQueue,
  removePlayerFromQueue,
} = require('./matchmakingFunctions/playerQueue');
const { matchmake } = require('./matchmakingFunctions/matchmake');
const {
  questionSelect,
  chooseQuestions,
  chooseQuestionAlt,
} = require('./gameFunctions/questionSelect');

/**
 * Initializes main io websocket connection
 *
 * @param {http.server} httpServerToBind - http server
 */
function socketServer(httpServerToBind) {
  const io = socketIO(httpServerToBind);

  io.on('connection', (socket) => {
    // Begin matchmaking for the selected player
    socket.on('matchmake', (player) => matchmake(io, socket, player));

    ... (Skipping some of the socket functions for clarity)

    socket.on('newTest', async () => {
      console.log('Inside newTest');
    });

    // When user disconnects (refreshes page, goes to another route), leave the queue
    socket.on('disconnect', () => removePlayerFromQueue('', socket));
  });

  return io;
}

module.exports = socketServer;

但是,我试图让玩家“选择问题”时,最后我们会向两个玩家的套接字发出一个事件。例如,我目前有一个 mocha 测试,设置如下:

...
const wsClient = require('socket.io-client');
const wsServer = require('../webServer');
...

describe('Question Selection', function beginTests() {
  let user1;
  let user2;
  let user3;
  let server;
  let io;

  before(async function connectServer() {
    [user1, user2, user3] = userMockData;

    server = http.createServer();
    io = wsServer(server);
    await databaseConnection();

    await Promise.all([Match.deleteMany({}), User.deleteMany({})]);

    user1 = await user1.save();
    user2 = await user2.save();
    user3 = await user3.save();

    await server.listen(port);
  });

  afterEach(async function cleanServer() {
    await Match.deleteMany({});
  });

  after(async function disconnectServer() {
    io.sockets.sockets.forEach((socket) => {
      socket.disconnect();
    });

    await Promise.all([io.close(), mongoose.disconnect()]);
  });

在这里,我正在运行一个测试来连接两个用户,让他们匹配,让他们选择他们想要使用的问题,然后向他们发送一个事件,告诉他们我们正在从问题选择转向游戏玩法。除了我遇到问题的最后一部分设置之外,我拥有一切。当前代码如下:

  it('Shift to Gameplay', function (done) {
    this.timeout(20000);
    const timeEpsilon = 9000;
    let client1;
    let client2;

    const interval = setInterval(async () => {
      // Get the earliest event that was made and process
      const earliestEvent = await Match.findOne({
        $or: [{ status: 'Question-Selection' }, { status: 'In-Match' }],
      }).sort('-updatedAt');

      if (earliestEvent) {
        // Process the event
        let timeToFinishTask = dayjs(earliestEvent.updatedAt);
        timeToFinishTask = timeToFinishTask.add(timeEpsilon, 'ms');
        const now = dayjs();

        if (earliestEvent.status === 'Question-Selection') {
          if (
            earliestEvent.player1.problems.length === 3 &&
            earliestEvent.player2.problems.length === 3
          ) {
            earliestEvent.status = 'In-Match';
            io.socket.to(earliestEvent.player1.socket).emit('newTest', {});

            await earliestEvent.save();
            done();
          } else if (timeToFinishTask <= now) {
            io.to(matchSettings.player1.socket).emit('newTest');
          }
        } else if (earliestEvent.status === 'In-Match') {
        }
      }
    }, 1000);

    client1 = wsClient.connect(socketURL, options);
    client1.on('connect', () => {
      client1.emit('addPlayer', { user: user1, gamemode: 'test' });
    });

    // Player1 connected, try to connect Player2
    client1.on('addedPlayer', () => {
      client2 = wsClient.connect(socketURL, options);
      client2.on('connect', () => {
        client2.emit('addPlayer', { user: user2, gamemode: 'test' });
        client2.on('addedPlayer', (player2) => {
          // Player2 connected, matchmake them
          client2.emit('matchmake', player2._id);
          client2.on('matchmade', async (matchSettings) => {
            assert(matchSettings.player1.userId === user2._id.toString());
            assert(matchSettings.player2.userId === user1._id.toString());

            // Get the questions from the database
            client2.emit('questionSelect', { matchSettings: matchSettings });

            // Get the questions pool back from the database
            client2.on('QuestionPool', (questionPoolPlayer2) => {
              client1.on('QuestionPool', (questionPoolPlayer1) => {
                assert(questionPoolPlayer1);
                assert(questionPoolPlayer2);
                assert(questionPoolPlayer1 !== questionPoolPlayer2);

                client1.emit('chooseQuestionAlt', {
                  user: user1,
                  questions: [],
                  questionPool: questionPoolPlayer1,
                });

                client2.emit('chooseQuestionAlt', {
                  user: user2,
                  questions: [
                    questionPoolPlayer2[0],
                    questionPoolPlayer2[1],
                    questionPoolPlayer2[2],
                  ],
                  questionPool: questionPoolPlayer2,
                });

                client1.on('questionsSavedAlt', (newMatchSettings1) => {});
                client2.on('questionsSavedAlt', (newMatchSettings2) => {});
              });
            });
          });
        });
      });
    });
  });
});

在 setInterval 函数中可以看到主要错误的一个示例。我有一个 io.to(matchSettings.player1.socket).emit() (matchsettings 文档存储了播放器的 socketid 以供以后参考),但是它永远不会被调用,因为控制台永远不会记录事件内部的字符串。在两个播放器在回调内连接后,我尝试过这样做,但这也失败了。我试过 io.to().emit() 和 io.emit(),但它不起作用。

我不能依赖客户端套接字,因为此信息在后端处理,然后发送到前端,前端输入不多。如果我遗漏了什么,或者如果有更好的方法可以做到这一点,我们将不胜感激。谢谢你。

标签: javascriptnode.jssocketssocket.io

解决方案


推荐阅读