Reputation: 33
I am making a turn based multiplayer game using the MERN stack and SocketIO. I want each player to have 60 seconds to play their turn before the game kicks them out. Once that player plays I want the timer to be canceled. I have tried creating a setTimeout function for each player in the game and then using clearTimeout to cancel the timer based on socketIO events, but the timers don't actually get canceled. It could be an implementation problem, so I was wondering what is the best way to implement this functionality? Here's my current implementation:
socket.on('Start Countdown', () => {
let user = getUser(socket.id);
user.countDown = setTimeout(() => {
socket.emit('Error', { error: { msg: 'You took too long' } });
socket.emit('AFK');
}, 60000);
});
socket.on('Stop Countdown', () => {
let user = getUser(socket.id);
if (user.countDown) {
clearTimeout(user.countDown);
console.log(user.countDown);
}
console.log(user.countDown);
});
As mentioned earlier, when "Stop Countdown" happens, the timer doesn't get canceled. Note: getUser returns a js object, user, of the form {socketId, userId, roomId, countDown} from a users array based on the provided socket.id. There will be no two elements in that array with the same userId and upon refresh, the socketId element will get updated to the correct socket.id. So you can assume that getUser will return the same user object every time, even after refresh.
Upvotes: 0
Views: 1208
Reputation: 171
I don't know how getUser
works, but if fetching from a database the user
var is destroyed when the Start Countdown
event ends, you can try to define an object and assign some unique property of the user such as the id
or the username
as the key and the timeout as the value:
var timeouts = {} //this must go outside the socket connection event
socket.on('Start Countdown', () => {
let user = getUser(socket.id);
//it could be user.id, user.username or some property of user that is unique and unvariable
timeouts[user.userId] = setTimeout(() => {
socket.emit('Error', { error: { msg: 'You took too long' } });
socket.emit('AFK');
}, 60000);
});
socket.on('Stop Countdown', () => {
let user = getUser(socket.id);
if (timeouts[user.userId]) {
clearTimeout(timeouts[user.userId]);
console.log(timeouts[user.userId]);
}
console.log(timeouts[user.userId]);
});
Upvotes: 0
Reputation: 126
Guess that should work, but you can try defining a new empty object where its ID is the client.id, so you assign it with the setTimeout value, from there you can check if there is a timer already running for that user or cancel it at the end.
const timers = {};
socket.on('Start Countdown', () => {
if (typeof timers[socket.id] !== 'undefined') {
clearTimeout(timers[socket.id]);
}
timers[socket.id] = setTimeout(() => {
socket.emit('Error', { error: { msg: 'You took too long' } });
socket.emit('AFK');
}, 60000);
});
socket.on('Stop Countdown', () => {
if (typeof timers[socket.id] !== 'undefined') {
clearTimeout(timers[socket.id]);
delete timers[socket.id];
}
});
Hope that helps you! 😁
Upvotes: 0