W drugiej części tworzenia chatu z Node.js i Socket.io użyjemy MongoDB do przechowywania wiadomości napisanych przez użytkowników.
Aby pobrać bazę danych MongoDB przejdź pod ten adres i wybierz odpowiednią dla swojego systemu wersję. Po pobraniu zainstaluj MongoDB. Instalacja jest bardzo prosta i polega głównie na klikaniu Next.
Po zainstalowaniu otwórzmy cmd i przejdźmy do folderu, w którym znajdują się pliki mongod.exe i mongo.exe. W moim przypadku jest to C:\MongoDB\bin. Przejdźmy do tego folderu:
Możemy teraz uruchomić bazę danych poniższą komendą:
mongod
Ten widok oznacza, że wszystko działa poprawnie i MongoDB zostało włączone. Otwórzmy kolejne okno cmd (nie zamykamy tego) i przechodzimy do tego samego folderu i wpisujemy komendę:
mongo
To tutaj zarządzamy naszą bazą danych. MongoDB znacznie różni się od baz danych takich jak mySQL. Przede wszystkim nie definiujemy tutaj tabel i kolumn. Są one automatycznie tworzone gdy otrzymają takie polecenie. Spróbujmy umieścić nowy rekord w tabeli messages wpisując w powyższym oknie cmd:
db.messages.insert( { username: "Devcorner", message: "Hello world." } )
Teraz możemy podejrzeć zawartość tej tabeli wpisując:
db.messages.find()
Zauważ, że nie definiowaliśmy wcześniej tabeli oraz kolumn. Wszystko zostało wygenerowane dynamicznie 🙂
Możemy teraz zająć się naszym kodem. Skoro mamy bazę danych, gdzie chcemy przechowywać wszystkie wiadomości to warto byłoby przechowywać również ich autorów. Przejdźmy do pliku index.html i zmodyfikujmy go tak, aby użytkownik musiał podać swoją nazwę przed wysłaniem wiadomości.
Skorzystamy z okna prompt aby użytkownik mógł wpisać swoją nazwę a następnie sprawdzimy czy faktycznie jakąś nazwę wprowadził:
var username = prompt("Nazwa:");
if(username) {
$('form').submit(function(){
socket.emit('message', {
message: $('#msg').val(),
username: username
});
$('#msg').val('');
return false;
});
socket.on('message', function(msg){
$('#messages').append($('<li>').text(msg.username + ": " + msg.message));
$("html, body").scrollTop($(document).height());
});
}
Na początku do zmiennej username przypisujemy nick podany przez użytkownika. Następnie sprawdzamy czy użytkownik cokolwiek wpisał. Jeśli tak to umożliwiamy użytkownikowi wysyłanie i odbieranie wiadomości. Podczas wysyłania wiadomości wysyłamy teraz również nazwę użytkownika.
Podczas odbierania wiadomości wyświetlamy teraz również nazwę użytkownika w formacie Nazwa: Wiadomość.
W nowym oknie cmd przejdźmy teraz do folderu z naszym chatem:
Zainstalujmy teraz obsługę MongoDB wpisując:
npm install mongodb
Po instalacji przejdźmy do pliku index.js – naszego serwera. Na samym początku pliku do zmiennej mongo przypiszmy zainstalowany moduł:
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
mongo = require('mongodb').MongoClient;
Dostosujmy teraz wcześniejszy kod do współpracy z bazą danych:
mongo.connect('mongodb://127.0.0.1/test', function(err, db){
if(err) throw err;
io.sockets.on('connection', function (socket) {
console.log("Socket connected.");
var col = db.collection('messages');
col.find().toArray(function(err, res){
if(err) throw err;
socket.emit('output', res);
});
socket.on('message', function(msg){
var whitespacePattern = /^\s*$/;
if(whitespacePattern.test(msg.username) || whitespacePattern.test(msg.message)) {
socket.emit('er', "Wiadomość i nazwa użytkownika nie może być pusta.");
}
else {
col.insert( { username: msg.username, message: msg.message} )
io.emit('message', {
message: msg.message,
username: msg.username
});
}
});
});
});
Na początku przy pomocy mongo.connect łączymy się z bazą test (jest domyślnie tworzona podczas instalacji Mongo). Jeśli wystąpił błąd połączenia to go zwracamy. Następnie łączymy się z Socket.io. Do zmiennej col przypisujemy skrót do naszej tabeli – usprawni to operacje na bazie.
Przy pomocy col.find().toArray pobieramy wszystkie wiadomości i konwertujemy je do tablicy. Tablicę przesyłamy (emit) do klienta (index.html). Podczas odbierania przez serwer wiadomości wysłanej przez użytkownika definiujemy wzór w zmiennej whitespacePattern. Następnie używamy test i sprawdziamy czy nazwa użytkownika lub wiadomość nie składają się wyłącznie z pustych znaków. Jeśli tak to przesyłamy informację o błędzie. W przeciwnym wypadku dodajemy nowy rekord do bazy danych i wysyłamy wiadomość do wszystkich użytkowników.
W ten sposób wiadomości z bazy danych zostaną pobrane tylko raz – przy dołączeniu do chatu. Nowe wiadomości będą pochodziły bezpośrednio z serwera.
Musimy teraz w pliku index.html odebrać wiadomości pobrane z bazy danych. Zaraz za var socket = io(); dodajmy kod:
socket.on('output', function(data){
if(data.length) {
for(var x=0; x < data.length; x++){
$('#messages').append($('<li>').text(data[x].username + ": " + data[x].message));
}
}
});
W pliku index.html przed zamykającym znacznikiem </script> dodajmy jeszcze obsługę błędu:
socket.on('er', function(er){
alert(er);
});
Jeśli pojawił się błąd to wyświetlamy komunikat z serwera. Jest to bardzo prosta walidacja, ale na potrzeby tego przykładu jest wystarczająca.
Możemy teraz uruchomić serwer:
I podejrzeć efekty naszej pracy pod adresem http://localhost:3000.
W kolejnej części przeniesiemy nasz chat z serwera lokalnego do chmury na Heroku.
Paczkę możesz pobrać tutaj.