Michael Lynch
Michael Lynch

Reputation: 3149

Why is my Socket.io event firing multiple times?

I am building a simple chat room with Socket.io. The user enters a desired username and submits the form.

I check if the username is in use and then fire the join event if the username is available, which adds them to the chat, but the join events seems to be firing for each user that is currently in the chat - not just once for the new user entering it.

Client

var socket = io();

// user enters desired username and submits form
$('#chat__join').on('submit', function() {

    // get username value
    var name = $('#chat__name').val();

    // send socket username to check if someone is already using it
    socket.emit('isUserInChat', name);

    return false;
});

// callback for when we know if user is already in chat or not
socket.on('isUserInChat', function(exists, name) {

    if(!exists) {

        // this only fires once per form submission
        console.log('username is available');

        // but this fires per user
        socket.emit("join", name);
    } else {
        // username is taken
        // display error message
    }
});

The socket.emit("join", name); line seems to fire once when the first person submits the form, which is correct. But then when a second person submits the form, the join event is fired twice. When a third person submits the form, it's fired three times. Why is the event firing per user? Shouldn't it only fire per form submission?

Server

var express = require('express'),
    app = express(),
    http = require('http').Server(app),
    io = require('socket.io')(http),
    usersObj = {
        users: []
    };

io.on('connection', function(socket) {

    socket.on('isUserInChat', function(username) {

        var flag = false;

        // for each user
        for(var i = 0; i < usersObj.users.length; i++) {

            // if username matches username that was entered
            if(usersObj.users[i].username == username) {

                // set flag to be true
                flag = true;
            }
        }

        // send client true or false
        io.emit('isUserInChat', flag, username);
    });

    socket.on('join', function(name) {

        // construct user
        var user = {
            id: socket.id,
            username: name
        };

        // add user to users object array
        usersObj.users.push(user);

        // send chat message
        io.emit('sendMsg', 'Chat Bot', name+' has connected to the server.');
    });
});

Upvotes: 3

Views: 4368

Answers (1)

Patrick Roberts
Patrick Roberts

Reputation: 51886

You seem confused, but you actually told the event to emit to every client. If you want it to echo only back to the client that's checking the availability

io.emit('isUserInChat', flag, username);

should be

socket.emit('isUserInChat', flag, username);

Upvotes: 3

Related Questions