Search code examples
javascriptnode.jssocketssocket.io

Socket.io executes function twice when refresh the page


I am using nodejs, express-handlebars and socket.io. I created a simple feature using UUID and socket io and want to create persistent rooms. Because I want to work with it in clean manner, I build controllers. I don't know if is a good idea, but somehow the socket controller executes the code inside when I refresh the page... That will create serious issues in my database...

  1. I started by creating the main events in server.js file:
const server = http.createServer(app);
const io = new Server(server);

io.on('connection', socket => {
    //User look for user and send invitation to chat
    lookForUserAndInvite(socket);

    //Rooms creation 
    createASingleRoom(socket);
});
  1. Than, I sent the functions in the controller, serverside: Here the data object will be received from the clientside. This is the object I want to store in my mongodb. ALso, this is getting executed twice
const createASingleRoom = socket => {
    socket.on('create_room', data => {
        const roomObject = {
            roomId:         uuidv4(),
            author:         data.author,
            invitedUsers:   data.invitedUsers || []
        };

        console.log('server', roomObject); //Logged this. This creates a new room each time I will refresh the page
    })
}

export default createASingleRoom;
  1. I used express handlebars here so I imported the io library CDN. Here I fetched the user data from my server endpoint, and emit the event create_room. For now I just populated it with an array...
<script src="/socket.io/socket.io.js"></script>
<script>

    const handlereateRoom = () => {
        socket.emit('create_room', {
            roomId: roomName,
            author: user._id,
            invitedUsers: ['numero1', 'numero2']
        });
    }

     document.addEventListener('DOMContentLoaded', async () => {
        //Execute this only after the document is fully loaded
        //Get the main user
        user = await fetchData();
        let url = window.location.origin + '/signup';
        

        //Get dom elements
        const roomName = document.querySelector('#roomName').value;

        if (user) {
            handlereateRoom()
        }

    
    });


</script>

I seen that each time I refresh the page, I get a new connection id SET, and therefore I also get a new UUID (an entirely other object). So I get a new socket, and a new object.

7spvSFlQ9YJubmgrAAAD
server {
  roomId: '6b20f71b-23ad-48d8-9a20-db8a78ae4dc8',
  author: '65b41b7c389a60d75ed9a2f3',
  invitedUsers: [ 'numero1', 'numero2' ]
}
EHdSu_RuZzkc7_8nAAAF
server {
  roomId: 'f641a9fc-0fa0-4b65-9186-c782a25fab57',
  author: '65b41b7c389a60d75ed9a2f3',
  invitedUsers: [ 'numero1', 'numero2' ]
}

Solution

  • as you said whenever page reloads, a new connection is set and you cannot do anything to avoid it However you can use express session to store details of the user, even after page is reloaded, and do necessary checks to avoid createASingleRoom being called by same person

    possibly create a seperate userID variable in client session, and maintain checks on that variable

    usage

    const session = require('express-session')
    
    app.use(session({
    secret: 'my-secret',
    resave: false, 
    saveUninitialized: false  
    }))
    
    app.get('/', (req, res)=>{
    req.session.userID = someRandomNumber
    })
    

    then keep check on that userID