Search code examples
javascriptmongodbmongoosesocket.iochat

Why is the text in MongoDB is only loading after I make some server update?


I'm trying to make a simple chat app, and save the history of the conversation so it can be on the page when the user connects to it. If I load the page, it doesn't work, but if I make any server change (like even only hitting ctrl + S, which makes nodemon reload the server) it appends the messages as I wanted. Why is this happening?

//server.js
const mongoose = require('mongoose');
const Msg = require('./models/messages')
const io = require('socket.io')(3000, {
    cors: {
        origin: "*"
    }
})

const mongoDB = 'mongodb+srv://12345678:[email protected]/message-database?retryWrites=true&w=majority'

mongoose.connect(mongoDB).then(() => console.log('connected'))

const users = {};

io.on('connection', (socket) => {
    console.log('new user');
    Msg.find().then(result => {
        socket.emit('output-message', result);
    })
    
    socket.on('username', myname => {
        users[socket.id] = myname;
        socket.broadcast.emit('user-connected', myname)
    })
    socket.on('send-chat-message', message => {
        const msg = new Msg({message:message, user:users[socket.id]});
        msg.save().then(() => {
            socket.broadcast.emit('chat-message', {message:message, name:users[socket.id]})
        })

    })
})

const socket = io('http://localhost:3000');

var messageContainer = document.getElementById('message-container')
var messageForm = document.getElementById('send-container')

var myname = prompt('Qual é o seu nome?');
appendMessage('You joined')
socket.emit('username', myname);

socket.on('chat-message', data => {
    appendMessage(`${data.name}: ${data.message}`);
})

socket.on('output-message', data => {
    for(let i = 0; i < data.length; i++) appendMessage(`${data[i].user}: ${data[i].message}`);
    console.log(data)
    
})

socket.on('user-connected', myname =>
{appendMessage(`${myname} connected`)}
)

messageForm.addEventListener('submit', e => {

    e.preventDefault();
    const message = document.getElementById('message-input').value;
    socket.emit("send-chat-message", message);
    appendOwnMessage(`You: ${message}`);
    document.getElementById('message-input').value = '';
})

function appendMessage(message) {
    const  a = document.createElement('div');
    const b = a.appendChild(document.createElement('p'))
    b.innerText = message;
    b.setAttribute("class", "received")
    messageContainer.append(a)
}

function appendOwnMessage(message) {
    const  a = document.createElement('div');
    const b = a.appendChild(document.createElement('p'));
    b.innerText = message;
    b.setAttribute("class", "sent")
    messageContainer.append(a)
}
<script defer src='http://localhost:3000/socket.io/socket.io.js'></script>
    <script defer src='script.js'></script>
    <link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <div id='test'></div>
    <div id= 'message-container'></div>
    <div id='test'></div>
    <form id='send-container'>
        <input id="message-input" type='text'>
        <button type='submit' id='send-button'>Send</button>
    </form>


Solution

  • Register your listeners before you wait for the username. You are missing the message.

    socket.on('chat-message', data => {
        appendMessage(`${data.name}: ${data.message}`);
    })
    
    socket.on('output-message', data => {
        for(let i = 0; i < data.length; i++) appendMessage(`${data[i].user}: ${data[i].message}`);
        console.log(data)
        
    })
    
    socket.on('user-connected', myname =>
    {appendMessage(`${myname} connected`)}
    )
    
    var myname = prompt('Qual é o seu nome?');
    appendMessage('You joined')
    socket.emit('username', myname);
    
    

    You might also consider sending the messages after they register the username.

    socket.on('username', myname => {
           Msg.find().then(result => {
            socket.emit('output-message', result);
            })
            users[socket.id] = myname;
            socket.broadcast.emit('user-connected', myname)
        })