In dit artikel laten we u zien hoe u een realtime chat-app bouwt met behulp van de volgende technologieën:
- Opnieuw
- Node.js + Express.js
- Socket.IO
- Heroku
Opnieuw
Redis is een open source (BSD-licentie), in-memory datastructuuropslag, die wordt gebruikt als database, cache en berichtenmakelaar. Het ondersteunt datastructuren zoals strings, hashes, lijsten, sets, gesorteerde sets met bereikquery's, bitmaps, hyperloglogs en georuimtelijke indexen met radiusquery's.
In deze applicatie-tutorial maken we verbinding met een van de clusters met behulp van ScaleGrid-hosting voor Redis™*.
Node.js
Een platform gebouwd op de JavaScript-runtime van Chrome voor het eenvoudig bouwen van snelle en schaalbare netwerkapps. Node.js maakt gebruik van een gebeurtenisgestuurd, niet-blokkerend I/O-model dat het lichtgewicht en efficiënt maakt, en dus perfect is voor gegevensintensieve realtime-applicaties die op gedistribueerde apparaten worden uitgevoerd.
Express.js
Een Node.js-framework. Node.js is een platform waarmee JavaScript buiten de webbrowser kan worden gebruikt voor het maken van web- en netwerktoepassingen. Dit betekent dat u de server en server-side code kunt maken voor een toepassing zoals de meeste andere webtalen, maar dan met JavaScript.
Socket.IO
Een JavaScript-bibliotheek voor realtime webapplicaties die realtime, bidirectionele communicatie tussen webclients en servers mogelijk maakt. Socket.IO heeft twee componenten:een client-side bibliotheek die in de browser wordt uitgevoerd, en een server-side bibliotheek voor Node.js. Beide componenten hebben bijna identieke API's.
Heroku
Een cloudplatform waarmee bedrijven apps kunnen bouwen, leveren, monitoren en schalen. Het Heroku-platform is de snelste manier om van idee naar URL te gaan en omzeilt al die infrastructuurproblemen.
In dit artikel wordt ervan uitgegaan dat Redis, Node.js en de Heroku Toolbelt al op uw computer zijn geïnstalleerd.
Instellen
Maak een map en geef deze een naam. Je kunt het overal op je computer maken, omdat Node.js geen speciale server zoals Apache/nginx nodig heeft.
Stap 1
Initialiseer een package.json-bestand door npm init
uit te voeren .
{ "name": "node-socket-redis-chat-scalegrid", "version": "0.0.1", "description": "A realtime chat application using Redis, Node.js and Socket.IO", "dependencies": { "body-parser": "^1.15.2", "express": "^4.10.2", "redis": "^2.6.3", "socket.io": "^1.7.1" }, "main": "index.js", "scripts": { "start": "node index.js" }, "engines": { "node": "4.1.1" } }
Stap 2
Installeer de volgende afhankelijkheden:
- expressjs
- socketio
- opnieuw
...en enkele andere hulpprogramma's:
- body-parser
door het volgende commando uit te voeren:
npm install --save expressjs socket.io redis body-parser
Stap 3
Maak een openbare map voor het opslaan van onze CSS- en JS-bestanden:
/public/css/main.css /public/js/main.js
Stap 4:
Maak een map met views voor het opslaan van ons HTML-hoofdbestand:
/views/index.html
Stap 5:
Maak een creds.json
bestand dat de inloggegevens bevat om verbinding te maken met ons Redis™-cluster. Het moet het volgende formaat hebben:
{ "user": "", "password": "", "host": "", "port": 6379 }
Stap 6:
Maak de index.js
bestand dat onze Node.js-code zal hosten en als startpunt voor Heroku zal dienen.
Stap 7:
Voeg een .gitignore
toe bestand zodat de map node_modules niet is ingecheckt in Heroku:
node_modules
Na het voltooien van de 7e stap, zou u de volgende structuur moeten hebben:
. ├── creds.json ├── index.js ├── package.json ├── public │ ├── css │ │ └── main.css │ └── js │ └── main.js └── views └── index.html
Stap 8
Nu alles is ingesteld, kunnen we beginnen met het schrijven van onze backend-code. Allereerst moeten we al onze modules binnenbrengen. Open dus het bestand index.js en plak het volgende:
var express = require('express'); var bodyParser = require('body-parser'); var app = express(); var http = require('http').Server(app); var io = require('socket.io')(http); var fs = require('fs'); var creds = ''; var redis = require('redis'); var client = ''; var port = process.env.PORT || 8080; // Express Middleware for serving static // files and parsing the request body app.use(express.static('public')); app.use(bodyParser.urlencoded({ extended: true })); // Start the Server http.listen(port, function() { console.log('Server Started. Listening on *:' + port); }); // Store people in chatroom var chatters = []; // Store messages in chatroom var chat_messages = [];
Voordat we kunnen beginnen met het schrijven van code, hebben we een cluster nodig waarop Redis draait. Gelukkig biedt ScaleGrid voor Redis™ een krachtige, met één klik en volledig beheerde hostingoplossing.
Als je nog geen lid bent, kun je je hier aanmelden voor een gratis proefperiode van 30 dagen.
Anders logt u in op uw dashboard en maakt u een nieuw Redis™-cluster onder de Redis™-sectie:
Nadat het maken van het cluster is voltooid, noteert u de bovenstaande informatie en voegt u deze toe aan de relevante velden van de creds.json
bestand.
Nu we onze inloggegevens hebben ingesteld, zijn we klaar om onze Redis-client in Node te maken die verbinding maakt met ons cluster en sleutel-waardeparen gaat opslaan.
Voeg de volgende code toe aan het index.js-bestand:
// Read credentials from JSON fs.readFile('creds.json', 'utf-8', function(err, data) { if(err) throw err; creds = JSON.parse(data); client = redis.createClient('redis://' + creds.user + ':' + creds.password + '@' + creds.host + ':' + creds.port); // Redis Client Ready client.once('ready', function() { // Flush Redis DB // client.flushdb(); // Initialize Chatters client.get('chat_users', function(err, reply) { if (reply) { chatters = JSON.parse(reply); } }); // Initialize Messages client.get('chat_app_messages', function(err, reply) { if (reply) { chat_messages = JSON.parse(reply); } }); }); });
De bovenstaande code doet twee dingen:
- Lees de inloggegevens van
creds.json
en maakt een Redis-client die wordt gebruikt om sleutelwaardebewerkingen uit te voeren - Zodra de klant klaar is, vullen we de
chatters
en dechat_messages
dus alle nieuwe leden die lid worden, kunnen de chatgeschiedenis zien.
We gaan nu een aantal API's schrijven om de chattoepassing af te handelen. We hebben de volgende API's nodig:
- Deelnemen aan kamer [POST]
- Ruimte [POST] verlaten
- Bericht verzenden [POST]
- Berichten ontvangen [GET]
- Leden verkrijgen [GET]
Laten we beginnen met de Join Room API. Dit wordt aangeroepen wanneer een nieuwe gebruiker de applicatie voor het eerst start en probeert deel te nemen aan de chatroom:
// API - Join Chat app.post('/join', function(req, res) { var username = req.body.username; if (chatters.indexOf(username) === -1) { chatters.push(username); client.set('chat_users', JSON.stringify(chatters)); res.send({ 'chatters': chatters, 'status': 'OK' }); } else { res.send({ 'status': 'FAILED' }); } });
Hier hebben we de API voor het verlaten van de chatroom:
// API - Leave Chat app.post('/leave', function(req, res) { var username = req.body.username; chatters.splice(chatters.indexOf(username), 1); client.set('chat_users', JSON.stringify(chatters)); res.send({ 'status': 'OK' }); });
Het bericht verzenden en opslaan:
// API - Send + Store Message app.post('/send_message', function(req, res) { var username = req.body.username; var message = req.body.message; chat_messages.push({ 'sender': username, 'message': message }); client.set('chat_app_messages', JSON.stringify(chat_messages)); res.send({ 'status': 'OK' }); });
Alle berichten in de kamer ontvangen:
// API - Get Messages app.get('/get_messages', function(req, res) { res.send(chat_messages); });
Alle leden ophalen:
// API - Get Chatters app.get('/get_chatters', function(req, res) { res.send(chatters); });
Zodra we alle API's hebben ingesteld, moeten we Socket.IO-code schrijven om gebeurtenissen uit te zenden wanneer bepaalde eigenschappen, zoals de volgende, worden bijgewerkt:
- Aantal kamers
- Berichten
// Socket Connection // UI Stuff io.on('connection', function(socket) { // Fire 'send' event for updating Message list in UI socket.on('message', function(data) { io.emit('send', data); }); // Fire 'count_chatters' for updating Chatter Count in UI socket.on('update_chatter_count', function(data) { io.emit('count_chatters', data); }); });
Deze gebeurtenissen worden vervolgens aan de voorkant opgepikt door de Socket.IO-bibliotheek, die op zijn beurt de gebruikersinterface bijwerkt.
Stap 9
Nu moeten we onze gebruikersinterface bouwen waarmee gebruikers kunnen inloggen en chatten.
Open de index.html
bestand en voeg de volgende code toe:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Node.js + Socket.io + Redis Chat | ScaleGrid</title> <link rel="stylesheet" href="css/main.css"> </head> <body> <div class="container"> <h1>Node.js + Socket.io + Redis Chat | ScaleGrid</h1> <div class="join-chat"> <label for="username">Username:</label> <input type="text" id="username" name="username" /> <input type="button" id="join-chat" value="Join Chat" /> </div><br /> <div class="chat-info"></div><br /> <div class="chat"> <div class="messages"></div> <textarea name="message" id="message" cols="90" rows="5" placeholder="Enter your message..."></textarea><br /><br /> <input type="button" id="send-message" data-username="" value="Send Message"> <input type="button" id="leave-chat" data-username="" value="Leave Chat"> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.6.0/socket.io.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="js/main.js"></script> </body> </html>
Stap 10
Om onze HTML te laten werken, moeten we een aantal JavaScript AJAX-gebeurtenissen toevoegen die de verschillende bewerkingen zullen afhandelen, zoals lid worden van een kamer, vertrekken, een bericht verzenden, enz.
De volgende code haalt het aantal chatters op zodat we de gebruikersinterface kunnen updaten over het totale aantal mensen in de kamer:
$.get('/get_chatters', function(response) { $('.chat-info').text("There are currently " + response.length + " people in the chat room"); chatter_count = response.length; //update chatter count });
Met deze code kunnen gebruikers lid worden van de chatroom. Onthoud dat gebruikersnamen uniek zijn en niet kunnen worden gedupliceerd:
$('#join-chat').click(function() { var username = $.trim($('#username').val()); $.ajax({ url: '/join', type: 'POST', data: { username: username }, success: function(response) { if (response.status == 'OK') { //username doesn't already exists socket.emit('update_chatter_count', { 'action': 'increase' }); $('.chat').show(); $('#leave-chat').data('username', username); $('#send-message').data('username', username); $.get('/get_messages', function(response) { if (response.length > 0) { var message_count = response.length; var html = ''; for (var x = 0; x < message_count; x++) { html += "<div class='msg'><div class='user'>" + response[x]['sender'] + "</div><div class='txt'>" + response[x]['message'] + "</div></div>"; } $('.messages').html(html); } }); $('.join-chat').hide(); //hide the container for joining the chat room. } else if (response.status == 'FAILED') { //username already exists alert("Sorry but the username already exists, please choose another one"); $('#username').val('').focus(); } } }); });
Hier is de code om gebruikers toe te staan de chatroom te verlaten:
$('#leave-chat').click(function() { var username = $(this).data('username'); $.ajax({ url: '/leave', type: 'POST', dataType: 'json', data: { username: username }, success: function(response) { if (response.status == 'OK') { socket.emit('message', { 'username': username, 'message': username + " has left the chat room.." }); socket.emit('update_chatter_count', { 'action': 'decrease' }); $('.chat').hide(); $('.join-chat').show(); $('#username').val(''); alert('You have successfully left the chat room'); } } }); });
Dit is de code die elke keer wordt uitgevoerd wanneer iemand een bericht verzendt:
$('#send-message').click(function() { var username = $(this).data('username'); var message = $.trim($('#message').val()); $.ajax({ url: '/send_message', type: 'POST', dataType: 'json', data: { 'username': username, 'message': message }, success: function(response) { if (response.status == 'OK') { socket.emit('message', { 'username': username, 'message': message }); $('#message').val(''); } } }); });
Het volgende is de Socket.IO-code die luistert naar gebeurtenissen van de backend en de gebruikersinterface bijwerkt. Bijvoorbeeld, nieuwe berichten toevoegen aan het berichtengebied, de chattertelling bijwerken, enz.:
socket.on('send', function(data) { var username = data.username; var message = data.message; var html = "<div class='msg'><div class='user'>" + username + "</div><div class='txt'>" + message + "</div></div>"; $('.messages').append(html); }); socket.on('count_chatters', function(data) { if (data.action == 'increase') { chatter_count++; } else { chatter_count--; } $('.chat-info').text("There are currently " + chatter_count + " people in the chat room"); });
En je bent klaar! Start de server op met npm start
en open meerdere browservensters om meerdere gebruikers te simuleren.
Een demo van de applicatie is hier beschikbaar: https://node-socket-redis-chat.herokuapp.com/
Bekijk voor het implementeren van deze applicatie op Heroku hun documenten: https://devcenter.heroku.com/categories/deployment
De volledige broncode is ook beschikbaar op GitHub zodat je kunt forken en waaraan je kunt werken:https://github.com/Scalegrid/code-samples/tree/sg-redis- node-socket-chat/redis-node-socket-chat
Zoals altijd, als je iets geweldigs bouwt, tweet ons er dan over @scalegridio.
Als je hulp nodig hebt met beheer en hosting voor Redis™, laat ons het dan voor je vereenvoudigen met onze professionele diensten.