Search code examples
javascriptwhile-loopwebsocketsocket.ionested-loops

Javascript while loop waits for increment instead of becoming an infinite loop


Right now in my nodejs socket.io 'game' I would like to cycle through all users currently online*, each having their opportunity to be a leader and click a button that would sequentially make the next user the leader (to, again, click a button that makes the next user the leader. You get the idea). My issue is that when I make the while loop wait for the 'leader' socket to trigger the leaderSelection event to increment the while loop, the while loop instead creates an infinite loop, crashing my browser. Simply put, how can I make a while loop wait (a theoretically infinite amount of time) until it gets incremented, instead of running infinitely. Hopefully this was clear enough. Here's my code:

while(i < ids.length) { //Go through all ids one by one
        //Select current id and make that person the leader
        socket.broadcast.to(ids[i]).emit('leader', { message: 'You are the leader for this round', options: 'THIS WOULD BE A SELECTION BUTTON FOR THE leaderSelection EVENT LISTENER'});
        //Loop through all the other people that are not the leader and say they are the users for this round
        for(var e = 0; e < ids.length; e++) {
            if(i == e) { //Skip current leader
                console.log('skipped ' + usernames[i]); 
                continue;
            } 
            socket.broadcast.to(ids[e]).emit('user', { message: 'You are a user for this round'});
        }
        //When the leader socket clicks the 'select' button, the while loop will go to the next person to be a leader
        socket.on('leaderSelection', function(data) {
            i++; //Here is the issue, the while loop crashes my browser trying to wait for the increment. 
        });
    }

Solution

  • You can't do this in a while loop, Javascript just doesn't work that way. A possible alternative approach:

    // Notify the current leader
    function notifyLeader(leader) {
        socket.broadcast.to(leader).emit('leader', { message: 'You are the leader for this round', options: 'THIS WOULD BE A SELECTION BUTTON FOR THE leaderSelection EVENT LISTENER'});
    }
    
    // Notify all users except the leader
    function notifyUsers(users, leader) {
        users
        .filter(user => user !== leader)
        .forEach(user => {
            socket.broadcast.to(user).emit('user', { message: 'You are a user for this round'});
        });
    }
    
    // In a round of play, notify the leaders and users
    // When the leaderSelection event comes in, start a new round
    // with the next leader
    function startRound(ids, leaderIndex) {
        notifyLeader(ids[index]);
        notifyUsers(ids, leaderIndex);
        socket.once('leaderSelection', () => {
            startRound(ids, ++leaderIndex);
        });
    }
    
    // Start the first round with leader 0
    startRound(ids, 0);