I'm creating a react application with socket.io. A part of the application includes a "question prompt" that is given to all the clients connected to the server. I'm having trouble with getting the backend server to continue operations only after it has received and answer from all of its clients. Here is the code below
SocketManager.js (aka Backend/Server)
const runGame = async (roomCode) => {
// Variables for the game
let prevAnswerSet = new Set();
const delay = ms => new Promise(res => setTimeout(res, ms));
const room = socketRooms.get(roomCode);
const settings = room.getSettings();
const players = room.generateImposters(settings.numImposters);
const roomSocket = io.to(roomCode);
// This socket emit event, sends all clients to an "intro" page for one second.
roomSocket.emit(START_GAME, players, settings);
console.log("START_GAME");
await delay(1000);
// This socket emit event, sends all clients to a NUMBER_TASK, where the users are asked to answer a question.
roomSocket.emit(SWITCH_SCREEN, NUMBERS_TASK, pickRandomQuestion(NumberPrompt));
console.log('NUMBERS_TASK');
await delay(10000);
/*
HELP NEEDED HERE
Ideally I would like an asynchronus function where the server can emit a message to
all clients, receive the answer choices they made, and add them to the prevAnswerSet **defined above**
await getAnswersFromClients() ;
*/
// This socket emit event sends all clients to a VOTE_VIEW page where all the responses to the previous question are displayed. I will be passing in the answers from the previous questions in this emit event.
roomSocket.emit(SWITCH_SCREEN, VOTE_VIEW /*, [...prevAnswerSet.keys()]*/);
console.log("VOTE_VIEW");
await delay(10000);
/*
CONTINUE GAME PROCESS
*/
}
NumbersTask.js (Frontend React Component)
function NumbersTask(props) {
const [answer, setAnswer] = useState(5);
useEffect(() => {
/*
HELP NEEDED HERE
Ideally looking for some socket event listener here that will send back to the server
the answer for this specific client.
*/
}, [answer]);
let buttons = [];
for(let i = 1; i <= 10; i++){
const b = <button key={i} onClick={()=>setAnswer(i)}>{i}</button>
buttons.push(b);
}
let prompt;
if (props.currQuestion !== null){
if(props.gameState.currPlayer.imposter) {
prompt = 'You are the imposter, pick a number and DEFEND YOUR SELF'
} else{
prompt = props.currQuestion;
}
}
return (
<div>
<h1>My response is {answer}</h1>
<h2>{prompt}</h2>
{ buttons }
</div>
)
}
export default NumbersTask
All clients are sent to a NUMBER_TASK page where they will have to answer a question. After Waiting 10 seconds (from the await delay(10000)), I wish to emit an event to all clients connected to the Server and get all their answers (answered or unanswered is fine). I would imagine the socket listener would be placed inside the useEffect React Hook inside of NumberTask.js.
This issue would be trivial if it were an event sent from the server to one client. In this situation I would use an acknowledgement/callback function on the server. However, acknowledgement/callback functions are not allowed when the socket server broadcasts emit events to multiple clients.
So overall, I think there are two parts to this question
- How do I receive all the answers from the clients, if there are no callbacks allowed when broadcasting emits?
- How do I create an async function that will allow the server to wait until all the responses have been recorded before moving on to the next page!
Also on a smaller note, I have a feeling that coding my backend like this might not be a best practice or good design so please comment on that as well.
Thank you
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…