4
\$\begingroup\$

This is a chat using Node.js, socket.io and MongoDB for storage.

I'd appreciate any feedback on what can be improved. I understand that this allows for non-unique usernames to be used, and it's currently a JavaScript prompt, however this is simply a demonstration for entering a username to test the functionality.

index.html

<!DOCTYPE html>
<html>
    <head>
        <title>Chat</title>
        <link rel="stylesheet" href="css/main.css">
    </head>
    <body>

        <div class="chat">
            <div class="chat-messages"></div>
            <textarea placeholder="Type your message"></textarea>
        </div>

        <script src="node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js"></script>
        <script>

            (function() {
                var socket = io.connect('http://127.0.0.1:8080'),
                    name = prompt('Enter your name');

                // Listen for output from server
                socket.on('output', function(data) {
                    var messages = document.querySelector('.chat .chat-messages');

                    if(data.length) {

                        // Loop results
                        for(var x = 0; x < data.length; x = x + 1) {
                            var message = document.createElement('div');

                            message.setAttribute('class', 'chat-message');
                            message.innerText = data[x].name + ': ' + data[x].message;

                            // Prepend
                            messages.appendChild(message);
                            messages.insertBefore(message, messages.firstChild);
                        }
                    }
                });

                // Listen for keydown
                document.querySelector('.chat textarea').addEventListener('keydown', function(event) {
                    var self = this;

                    // Is enter down (without shift being held)?
                    if(event.which === 13 && event.shiftKey === false) {

                        if(name) {
                            // Send message
                            socket.emit('input', {
                                name: name,
                                message: self.value
                            });

                            self.value = '';
                        }

                        event.preventDefault();
                    }
                });
            })();
        </script>

    </body>
</html>

server.js

var mongo = require('mongodb').MongoClient,
    client = require('socket.io').listen(8080).sockets;

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

    // Connect to MongoDB
    mongo.connect('mongodb://127.0.0.1/chat', function(err, db) {
        if(err) throw err;

        var col = db.collection('messages');

        // Emit all messages
        col.find().limit(100).sort({_id: 1}).toArray(function(err, res) {
            if(err) throw err;
            socket.emit('output', res);
        });

        // Wait for input
        socket.on('input', function(data) {
            col.insert({name: data.name, message: data.message}, function(err, docs) {

                // Emit latest message to all clients
                client.emit('output', [data]);
            });
        });
    });

});

main.css (not as important here)

body,
textarea {
    font: 13px "Trebuchet MS", sans-serif;
}

.chat {
    max-width:300px;
}

.chat-messages,
.chat textarea {
    border:1px solid #bbb;
}

.chat-messages {
    width:100%;
    height:300px;
    overflow-y:scroll;
    padding:10px;
}

.chat-message {
    margin-bottom:10px;
}

.chat textarea {
    border-top:0;
    margin:0;
    max-width:100%;
    width:100%;
    padding:10px;
}

.chat textarea:focus {
    outline:none;
}
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

You should only open one connection to mongodb. Otherwise if you have 10 users connected on your chat, you'll have 10 opened connections to mongodb.

var mongo = require('mongodb').MongoClient;
var sio = require('socket.io');

mongo.connect('mongodb://127.0.0.1/chat', function(err, db) {
  if(err) throw err;

  var messages = db.collection('messages');

  client = sio.listen(8080).sockets;
  client.on('connection', function(socket) {
    messages.find().limit(100).sort({_id: 1}).toArray(function(err, res) {
      if(err) throw err;

      socket.emit('output', res);
    });

    socket.on('input', function(data) {
      messages.insert({name: data.name, message: data.message}, function(err, docs) {
        client.emit('output', [data]);
      });
    });
  });
});

From there, I would split the code into small functions. One could be call onInputMessage and looks something like.

var onInputMessage = function(data) {
  message.insert({name: data.name, message: data.message}, function(err, docs) {
    client.emit('output', [data]);
};

So that you can call it like this socket.on('input', onInputMessage);

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.