I've made a quiz game using socket.io. When a new socket connects, this runs:
io.on('connection', function (socket) {
let gameTimer = null;
After receiving a certain socket from the client, this function starts:
gameTimer = setTimeout(function () {
//Reveal if the players' answers are right or wrong
revealAnswer(answeredPlayers, playerData[socket.id].room);
//Start the countdown for the next question
countToNextQuestion(playerData[socket.id].room);
}, 21000)
When a player answers, this socket function runs in the server:
socket.on('Answered Question', function (userAnswer, answeredPlayerUsername, timeAnswered) {
//Stop the count
clearTimeout(gameTimer);
/*
*Extra code below that works...
*/
But this does not stop the timeout. Any reason why this is happening, and how to fix it?
EDIT: Here's the full socket code. It's a bit long, apologies:
io.on('connection', function (socket) {
console.log('Someone connected');
//Will hold the questions used for the session
let gameSessionQuestions = null;
//Holds the current question
let currentQuestion = null;
//Holds the correct answer to the current question
let currentQuestionAnswer = null;
//Give the socket player details
//and add this player to the dictionary
playerData[socket.id] = {
name: null,
room: null,
host: false,
score: 0
};
//Timer for questions
let gameTimer = null;
/*
SOCKET OPERATIONS
*/
socket.on('Get Total Score', async function(playerUsername){
let playerTotalScore = await gameController.getTotalScore(playerUsername);
socket.emit('Receive Total Score', playerTotalScore);
})
//Adds a room to the list of rooms
socket.on('Add Room', function (questionType) {
let newRoom = newRoomCreation(questionType);
//Since this player created the room, assign them the host value
playerData[socket.id].host = true;
playerData[socket.id].room = newRoom;
socket.join(newRoom);
io.sockets.to(newRoom).emit('Room Added', newRoom);
})
//Make the specified room a closed room
socket.on('Close the room', function (room) {
closeRoom(room);
})
socket.on('Room Availability', function (roomCode, questionType) {
if (!roomMap.get(roomCode)) {
socket.emit('Unavailable Room');
}
else {
//Check if the room has the question type the user chose
if (roomQuestionType.get(roomCode) == questionType) {
socket.emit('Available Room');
} else {
socket.emit('Unavailable Room');
}
}
})
socket.on('Open Room Availability', function (questionType) {
let roomFound = false;
for (let room of roomMap.keys()) {
if (!closedRoomsList.includes(room)) {
if (roomQuestionType.get(room) == questionType) {
roomFound = true;
socket.emit('Available Open Room', room);
}
}
}
if (roomFound == false) {
socket.emit('Unavailable Open Room');
}
})
socket.on('Join Room', function (values) {
//Give this player's 'name' variable a value
playerData[socket.id].name = values.p1;
//Give this player's 'room' variable a value
playerData[socket.id].room = values.p2;
//DELETE SOON: Checking the data before addition
console.log("Data in the room '" + values.p2 + "' before addition: ");
console.log(roomMap.get(values.p2));
//Put this player in the new room
socket.join(values.p2);
//Add the player's socketID and Name to the Room Map
let playersList = roomMap.get(values.p2);
playersList.push(values.p1);
//DELETE SOON: Checking the data after addition
console.log("Data in the room '" + values.p2 + "' after addition: ");
console.log(roomMap.get(values.p2));
io.sockets.to(values.p2).emit('Output Players', playersList);
if (playerData[socket.id].host == true) {
io.sockets.to(playerData[socket.id].room).emit('Current Host');
}
})
socket.on('Request Game Start', async function (room) {
//Checks if the user who started the game truly is the host
if (playerData[socket.id].host == false) {
return;
}
//Holds all the questions to be asked and their answers
gameSessionQuestions = await selectedQuestions(2, roomQuestionType.get(room));
//Reset the 'answered player' count
answeredPlayers.set(playerData[socket.id].room, 0);
io.sockets.to(room).emit('Game Start');
})
socket.on('Start Game Countdown', function () {
let pos = 0;
let countArr = ["2", "1", "Go"];
let counter = setInterval(function () {
//Update the count for all those in the room
io.sockets.to(playerData[socket.id].room).emit('Update Countdown', countArr[pos]);
if (pos == countArr.length) {
clearInterval(counter);
io.sockets.to(playerData[socket.id].room).emit('End Countdown');
currentQuestion = getQuestion(gameSessionQuestions[0], playerData[socket.id].room);
io.sockets.to(playerData[socket.id].room).emit('Receive Questions', currentQuestion);
//Holds the answer for the current question
currentQuestionAnswer = currentQuestionCorrectAnswer(gameSessionQuestions[0], playerData[socket.id].room);
//The answer to the question presented in this room is stored here
questionAnswers.set(playerData[socket.id].room, currentQuestionAnswer);
gameTimer = setTimeout(function () {
//Reveal if the players' answers are right or wrong
revealAnswer(answeredPlayers, playerData[socket.id].room);
//Start the countdown for the next question
countToNextQuestion(playerData[socket.id].room);
}, 21000)
} else {
pos++;
}
}, 1000);
})
socket.on('Answered Question', function (userAnswer, answeredPlayerUsername, timeAnswered) {
socket.broadcast.to(playerData[socket.id].room).emit('Display Answered Player', answeredPlayerUsername);
//DELETE SOON: Check the current question
console.log("Current Question's Answer: " + questionAnswers.get(playerData[socket.id].room));
console.log("Your answer: " + userAnswer);
let answerResult;
if (questionAnswers.get(playerData[socket.id].room) === userAnswer) {
answerResult = "btn-success";
//Add to the person's overall score
playerData[socket.id].score = addToScore(playerData[socket.id].score, timeAnswered);
socket.emit('Answer Check', answerResult);
}
else {
answerResult = "btn-danger";
socket.emit('Answer Check', answerResult);
}
//DELETE SOON: Checks the scores for the user
console.log("The score for '" + playerData[socket.id].name + "' is '" + playerData[socket.id].score + "'")
//Add 1 to the number of people who have answered in this room
answeredPlayers.set(playerData[socket.id].room, (answeredPlayers.get(playerData[socket.id].room)) + 1)
//DELETE SOON: Checks if the value is updating
console.log("Number of people who have answered: " + answeredPlayers.get(playerData[socket.id].room))
//If all users in the room have answered...
if (answeredPlayers.get(playerData[socket.id].room) == (roomMap.get(playerData[socket.id].room)).length) {
//DELETE SOON: Outputs message confirming all users answering
console.log("Everyone has answered");
//Stop the count
clearTimeout(gameTimer);
//Reveal if the players' answers are right or wrong
revealAnswer(answeredPlayers, playerData[socket.id].room);
//Start the countdown for the next question
countToNextQuestion(playerData[socket.id].room);
}
})
//Get the next question from the host
socket.on('Find Host', async function () {
if (playerData[socket.id].host == true) {
//DELETE SOON: Check the number of questions before
console.log('Question count before: ' + gameSessionQuestions.length)
gameSessionQuestions.shift();
//DELETE SOON: Check the number of questions after removing the one just asked
console.log('Question count after: ' + gameSessionQuestions.length)
//If there are still questions to be asked, send the next question and set the new correct answer
if (gameSessionQuestions.length != 0) {
//Get the next question and send it
currentQuestion = getQuestion(gameSessionQuestions[0], playerData[socket.id].room);
io.sockets.to(playerData[socket.id].room).emit('Receive Questions', currentQuestion);
//Get this question's correct answer
currentQuestionAnswer = currentQuestionCorrectAnswer(gameSessionQuestions[0], playerData[socket.id].room);
questionAnswers.set(playerData[socket.id].room, currentQuestionAnswer);
gameTimer = setTimeout(function () {
//Reveal if the players' answers are right or wrong
revealAnswer(answeredPlayers, playerData[socket.id].room);
//Start the countdown for the next question
countToNextQuestion(playerData[socket.id].room);
}, 21000)
} else {
//Holds the username and scores for all users in this room
let players_Scores = [];
let roomCode = playerData[socket.id].room;
let playerKeys = Object.keys(playerData);
for (let i = 0; i < playerKeys.length; i++) {
if (playerData[playerKeys[i]].room == roomCode) {
let scoreDetails = {
username: playerData[playerKeys[i]].name,
score: playerData[playerKeys[i]].score
}
players_Scores.push(scoreDetails)
await gameController.uploadScore(playerData[playerKeys[i]].name, playerData[playerKeys[i]].score, roomQuestionType.get(roomCode));
}
}
io.sockets.to(roomCode).emit('Show Scores', players_Scores);
}
}
})
//Remove details while reloading the menu page
socket.on('Back to Start', function () {
//Remove the player from the room in socketio
socket.leave(playerData[socket.id].room);
//If this is the host, delete the room
if (playerData[socket.id].host == true) {
roomMap.delete(playerData[socket.id].room);
roomQuestionType.delete(playerData[socket.id].room);
questionAnswers.delete(playerData[socket.id].room);
answeredPlayers.delete(playerData[socket.id].room);
}
//Remove this player's details
delete playerData[socket.id];
})
socket.on('disconnect', function () {
if (playerData[socket.id] && roomMap.get(playerData[socket.id].room) != undefined) {
//DELETE SOON: Check who left and from which room
console.log(playerData[socket.id].name + " has left the room '" + playerData[socket.id].room + "'");
//If on the lobby page, remove that player and update everyone's lists
let playerList = roomMap.get(playerData[socket.id].room);
playerList.splice(playerList.indexOf(playerData[socket.id].name), 1);
io.sockets.to(playerData[socket.id].room).emit('Output Players', playerList);
/*If this is the host,
* stop game timer
* alert all the players in the room,
* delete the room they were in*/
if (playerData[socket.id].host == true) {
clearTimeout(gameTimer);
socket.broadcast.to(playerData[socket.id].room).emit('Host Left');
roomMap.delete(playerData[socket.id].room);
roomQuestionType.delete(playerData[socket.id].room);
questionAnswers.delete(playerData[socket.id].room);
answeredPlayers.delete(playerData[socket.id].room);
}
delete playerData[socket.id];
}
})
})
Your issue in the smallest code to rep
let gameTimer;
let pos = 0;
let countArr = ["2", "1", "Go"];
let counter = setInterval(function () {
if (pos == countArr.length) {
console.log("Creating a new gameTimer", Date.now());
gameTimer = setTimeout(function () {
console.log('gameTimer executed')
}, 2100);
} else {
pos++;
}
}, 1000);
So your code keeps creating new timeouts. The previous timeouts exist, they do not get removed.
So you need to either remove the gameTimer before you create a new one, or do not create gameTimer if it is already running
let gameTimer;
let pos = 0;
let countArr = ["2", "1", "Go"];
let counter = setInterval(function () {
if (pos == countArr.length) {
if (gameTimer) return; // if gameTimer is defined, exit
console.log("Creating a new gameTimer", Date.now());
gameTimer = setTimeout(function () {
console.log('gameTimer executed')
}, 2100);
} else {
pos++;
}
}, 1000);