MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Bate-papo em tempo real com Modulus e Node.js


Neste tutorial, mostrarei como implementar um aplicativo de bate-papo em tempo real com Node.js, Socket.IO e MongoDB e, em seguida, implantaremos esse aplicativo no Modulus juntos.

Antes de mais nada, deixe-me mostrar o visual final do aplicativo que teremos no final do artigo.

Node.js será o núcleo da aplicação, com Express como MVC, MongoDB para o banco de dados e Socket.IO para comunicação em tempo real. Quando terminarmos, implantaremos nosso aplicativo no Modulus. A parte MongoDB realmente existe dentro do Modulus.

1. Cenário

  1. João deseja usar nosso aplicativo e o abre no navegador.
  2. Na primeira página, ele seleciona um apelido para usar durante o bate-papo e faz login no bate-papo.
  3. Na área de texto, ele escreve algo e pressiona Enter.
  4. O texto é enviado para um serviço RESTful (Express) e esse texto é gravado no MongoDB.
  5. Antes de escrever no MongoDB, o mesmo texto será transmitido para os usuários que estão logados no aplicativo de bate-papo.

Como você pode ver, este é um aplicativo muito simples, mas cobre quase tudo para um aplicativo da web. Não há sistema de canal neste aplicativo, mas você pode bifurcar o código-fonte e implementar o módulo de canal para praticar.

2. Design do projeto do zero


Vou tentar explicar as pequenas partes do projeto primeiro e combiná-las no final. Vou começar do back-end para o front-end. Então, vamos começar com os objetos de domínio (modelos MongoDB).

2.1. Modelo


Para abstração de banco de dados, usaremos Mongoose. Neste projeto, temos apenas um modelo chamado Message . Este modelo de mensagem contém apenas text , createDate ,  e author . Não há modelo para o autor como User porque não implementaremos totalmente um sistema de registro/login de usuário. Haverá uma página simples de fornecimento de apelidos, e esse apelido será salvo em um cookie. Isso será usado na Message modelo como texto no arquivo author campo. Você pode ver um exemplo de modelo JSON abaixo:
{

    text: "Hi, is there any Full Stack Developer here?"

    author: "john_the_full_stack",

    createDate: "2015.05.15"

}

Para criar documentos como este, você pode implementar um modelo usando as funções do Mongoose abaixo:
var mongoose = require('mongoose')



var Message = new mongoose.Schema({

    author: String,

    message: String,

    createDate: {

        type: Date,

        default: Date.now

    }

});



mongoose.model('Message', Message)

Basta importar o módulo Mongoose, definir seu modelo com seus campos e atributos de campo no formato JSON e criar um modelo com o nome Message . Este modelo será incluído nas páginas que você deseja usar.

Talvez você tenha alguma dúvida sobre por que estamos armazenando a mensagem no banco de dados, quando já transmitimos essa mensagem para o usuário no mesmo canal. É verdade que você não precisa armazenar mensagens de bate-papo, mas eu só queria explicar a camada de integração do banco de dados. De qualquer forma, usaremos este modelo em nosso projeto dentro dos controladores. Controladores?

2.2. Controlador


Como eu disse anteriormente, usaremos o Express para a parte MVC. E C   aqui significa o Controller . Para nossos projetos, haverá apenas dois endpoints para mensagens. Um deles é para carregar mensagens de bate-papo recentes e o segundo é para lidar com mensagens de bate-papo enviadas para armazenar no banco de dados e depois difundir no canal.
.....

app.get('/chat', function(req, res){

    res.sendFile(__dirname + '/index.html');

});



app.get('/login', function(req, res){

    res.sendFile(__dirname + '/login.html');

});



app.post('/messages', function(req, res, next) {

    var message = req.body.message;

    var author = req.body.author;

    var messageModel = new Message();

    messageModel.author = author;

    messageModel.message = message;

    messageModel.save(function (err, result) {

       if (!err) {

           Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) {

               io.emit("message", messages);

           });

           res.send("Message Sent!");

       } else {

           res.send("Technical error occurred!");

       }

    });

});



app.get('/messages', function(req, res, next) {

    Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) {

        res.json(messages);

    });

});

.....

O primeiro e o segundo controladores são apenas para servir arquivos HTML estáticos para as páginas de bate-papo e login. O terceiro é para lidar com a solicitação de postagem para o arquivo /messages   endpoint para criar novas mensagens. Nesse controlador, primeiro o corpo da solicitação é convertido para o modelo Message e, em seguida, esse modelo é salvo no banco de dados usando a função Mongoose save . 

Não vou me aprofundar muito no Mongoose - você pode dar uma olhada na documentação para mais detalhes. Você pode fornecer uma função de retorno de chamada para a função salvar para verificar se há algum problema ou não. Se for bem-sucedido, buscamos os últimos cinco registros classificados em ordem decrescente por createDate , e transmitiram cinco mensagens para os clientes no canal.

Ok, terminamos MC .  Vamos mudar para a View papel.

2.3. Visualizar


Em geral, um mecanismo de modelo como Jade, EJS, Handlebars, etc., pode ser usado no Express. No entanto, temos apenas uma página, e essa é uma mensagem de bate-papo, então servirei estaticamente. Na verdade, como eu disse acima, há mais dois controladores para veicular esta página HTML estática. Você pode ver o seguinte para servir uma página HTML estática.
app.get('/chat', function(req, res){

    res.sendFile(__dirname + '/index.html');

});



app.get('/login', function(req, res){

    res.sendFile(__dirname + '/login.html');

});

Esse endpoint simplesmente veicula index.html e login.html usando res.sendFile . Ambos  index.html e login.html estão na mesma pasta que server.js, razão pela qual usamos __dirname antes do nome do arquivo HTML.

2.4. Front-end


Na página de front-end, usei o Bootstrap e não há necessidade de explicar como consegui fazer isso. Simplesmente, vinculei uma função a uma caixa de texto e sempre que você pressiona a tecla Enter  chave ou Enviar  botão, a mensagem será enviada para o serviço de back-end.

Esta página também tem um arquivo js necessário do Socket.IO para ouvir o canal chamado message . O módulo Socket.IO já é importado no back-end e, quando você usa esse módulo no lado do servidor, ele adiciona automaticamente um endpoint para servir o arquivo Socket.IO js, mas usamos aquele que é servido a partir do cdn <script src="//cdn.socket.io/socket.io-1.3.5.js"></script> . Sempre que uma nova mensagem chegar a este canal, ela será automaticamente detectada e a lista de mensagens será atualizada com as últimas cinco mensagens.
<script>

        var socket = io();

        socket.on("message", function (messages) {

            refreshMessages(messages);

        });



        function refreshMessages(messages) {

            $(".media-list").html("");

            $.each(messages.reverse(), function(i, message) {

                $(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div class="media-body">'

                + message.message + '<br/><small class="text-muted">' + message.author + ' | ' + message.createDate + '</small><hr/></div></div></div></li>');

            });

        }



        $(function(){



            if (typeof $.cookie("realtime-chat-nickname") === 'undefined') {

                window.location = "/login"

            } else {

                $.get("/messages", function (messages) {

                    refreshMessages(messages)

                });



                $("#sendMessage").on("click", function() {

                    sendMessage()

                });



                $('#messageText').keyup(function(e){

                    if(e.keyCode == 13)

                    {

                        sendMessage();

                    }

                });

            }



            function sendMessage() {

                $container = $('.media-list');

                $container[0].scrollTop = $container[0].scrollHeight;

                var message = $("#messageText").val();

                var author = $.cookie("realtime-chat-nickname");

                $.post( "/messages", {message: message, author: author}, function( data ) {

                    $("#messageText").val("")

                });

                $container.animate({ scrollTop: $container[0].scrollHeight }, "slow");

            }

        })

    </script>

Há mais uma verificação no código acima:a parte do cookie. Se você não escolheu nenhum apelido para o bate-papo, significa que o cookie não está definido para o apelido e você será redirecionado automaticamente para a página de login.

Caso contrário, as últimas cinco mensagens serão buscadas por uma simples chamada Ajax para o arquivo /messages ponto final. Da mesma forma, sempre que você clicar no botão Enviar ou pressione o botão Enter key, a mensagem de texto será buscada na caixa de texto, e o apelido será buscado no cookie, e esses valores serão enviados ao servidor com uma solicitação de postagem. Não há uma verificação rigorosa para o apelido aqui, porque eu queria focar na parte em tempo real, não na parte de autenticação do usuário.

Como você pode ver, a estrutura geral do projeto é muito simples. Vamos para a parte de implantação. Como disse anteriormente, usaremos o Modulus, um dos melhores PaaS para implantar, dimensionar e monitorar sua aplicação no idioma de sua escolha.

3. Implantação

3.1. Pré-requisitos


A primeira coisa que me vem à mente é mostrar como implantar, mas para uma implantação bem-sucedida, precisamos de um banco de dados funcional. Vamos dar uma olhada em como criar um banco de dados no Modulus e, em seguida, realizar a implantação.

Vá para o painel do Modulus depois de criar uma conta. Clique em Bancos de dados  menu à esquerda e clique em Criar banco de dados.

Preencha os campos obrigatórios no formulário pop-up conforme abaixo.

Ao preencher os campos obrigatórios e clicar em Criar,  ele criará um banco de dados MongoDB para você e você verá a URL do banco de dados na tela. Usaremos MONGO URI ,  então copie esse URI.

Em nosso projeto, o Mongo URI é obtido da variável de ambiente MONGO_URI , e você precisa definir essa variável de ambiente no painel. Vá para o painel, clique em Projetos menu, selecione seu projeto na lista e clique em Administração no menu esquerdo. Nesta página, você verá a seção de variáveis ​​de ambiente ao rolar a página, conforme mostrado abaixo.

Você pode implantar no Modulus de duas maneiras:
  • fazer upload do arquivo ZIP do projeto usando o painel
  • implantação a partir da linha de comando usando o Modulus CLI

Vou continuar com a opção de linha de comando, porque a outra é fácil de fazer. Primeiro de tudo, instale o Modulus CLI:
npm install -g modulus

Vá para a pasta do seu projeto e execute o seguinte comando para fazer login no Modulus.
modulus login

Ao executar o comando acima, você será solicitado a inserir um nome de usuário e senha:

Se você criou uma conta usando o GitHub, pode usar o comando --github opção.
modulus login --github

Agora você está logado no Modulus e é hora de criar um projeto. Use o seguinte comando para criar um projeto:
modulus project create "Realtime Chat"

Ao executar esta função, será solicitado o tempo de execução. Selecione a primeira opção, que é Node.js, e a segunda será solicitado o tamanho do servo, podendo mantê-lo como padrão.

Criamos um projeto, e desta vez vamos implantar nosso projeto atual no Modulus. Execute o seguinte comando para enviar o projeto atual para o Realtime Chat projeto no lado do módulo.
modulus deploy

Ele implantará seu projeto e você obterá a URL do projeto em execução no final da mensagem de implantação bem-sucedida:
Realtime Chat running at realtime-chat-46792.onmodulus.net

Como você pode ver, a implantação no Modulus é muito fácil!

O Modulus CLI tem comandos muito úteis para usar durante a implantação do projeto ou em tempo de execução. Por exemplo, para encerrar os logs do seu projeto em execução, você pode usar modulus project logs tail , para criar um banco de dados MongoDB use modulus mongo create <db-name> , para definir uma variável de ambiente, use modulus env set <key> <value> , etc. Você pode ver uma lista completa de comandos usando a ajuda do Modulus.