Home > OS >  emit function from client side to all room only once, socket.io
emit function from client side to all room only once, socket.io

Time:07-09

I am a newbie with socket.io and I have a hard time figuring out how to correctly use server and client. So, I have a function on my client side that listens to the server to get an array of questions to display it to the room.

The idea is to create a room with several clients connected, and to emit to one room a function from the client side (only once, as I want to display the information to all the room). I really need this function on my client side as I have approximately 100 lines of code that concerns the front. Also my server needs to emit its array to the client. My problem is, since it is client side, when I emit it to the server it will be emitted x times the number of clients inside the room. And I wish to emit it only once.

To have a concrete example : My server has an object of array which is passed to the clients in a room so they can display it. Here is the function in the client :

//I have shorten the function so it is not too much but you can still grasp how I need it in my client
socket.on('getNewQuestion', (currentQuestion) => {

init();
questionNumber.innerHTML = "Question "   countQuestion;
questionParams.id = currentQuestion.questionId;
questionParams.questionTxt = currentQuestion.question;
questionParams.reponse = JSON.parse(currentQuestion.reponse);
questionParams.lien = currentQuestion.lien;
questionParams.type = currentQuestion.type;

//Display question text
questionTxt.innerHTML = currentQuestion.question;

//Display different informations according to the question's type
switch (currentQuestion.type) {
    case "enigme":
        var getReponseLength = JSON.parse(currentQuestion.reponse)[0].length;
        questionType.innerHTML = "find the answer to this question with "   getReponseLength   " letters";

        break;

    case "anagramme":

        questionType.innerHTML = "find a word usign all these letters :";
        const html = [];
        //Parse string to create array of chars
        var questionParse = JSON.parse(currentQuestion.question);
        //Gets the characters of the string and shuffles it 
        for (let i = questionParse.length - 1; i >= 0; i--) {
            const randLetters = Math.floor(Math.random() * (i   1));
            [questionParse[i], questionParse[randLetters]] = [questionParse[randLetters], questionParse[i]];
            html.push(`<div>${questionParse[i]}</div>`);//display letter
        }
        currentQuestion.question = questionParse;
        questionTxt.innerHTML = html.join(" ");
        break;
}
countQuestion  ;
});

Then I emit it in my server to get the object of question

  socket.on('callGetNewQuestion', (roomCode) => {
    //Get a random question from the object
    const questionCalled = questions.getQuestionsList(roomCode)[Math.floor(Math.random() * questions.getQuestionsList(roomCode).length)];
    io.in(roomCode).emit('getNewQuestion', questionCalled); //emit the random question to the client
    questions.removeQuestion(questionCalled.questionId); //remove it so it doesn't appear twice
  });

And I am emitting back in my client (which I am not sure if it is good practice but I don't have any idea on how to listen to the object otherwise)

socket.on('startGame', () => {
    socket.emit('callGetNewQuestion', userParams.roomCode);
    timerCountdownGame();
});

The problem with this code is : as it is called from the client side, if there is two clients in the room it is called twice, if there are three clients, it is called three times, so when I start the game it will pass from question 1 to question 3 (if number of clients is three). I hope what I am saying makes sense, if not do not hesitate to tell me

Does anyone know how I can correct it ?

CodePudding user response:

The main problem you are having is that the server behaviour is driven by the client, which should be the opposite...

Why should your client request a new question? Your server should send the new question whenever it is available. If really you need to have your client request question, you should store the current question in your room and send the currentQuestion, not generate it.

I think your room should keep some state, like game started, waiting for clients etc... Clients all send a ready, once all clients are ready room generates a question and sends it to all clients. Something like so.

  • Related