Beginners Step-by-Step Guide For Building Apps with Node.js ~ Coding Savvy
FB Twitter Google
» »

Beginners Step-by-Step Guide For Building Apps with Node.js

I just discovered that node.js has been one of the hidden treasure on the internet, I did not get to know much about node.js until the last two years but I have always installed it on my system until about some weeks ago I decide to take it for a spin and that's when i knew that node.js has the solution to one of my most used technique in programming, if you have read my tutorial on how i manage to keep my objects alive from the database on the server to the client side. But the incredible thing is that it a very simple task to be achieved using node.js which makes node very awesome to me. you really need to see this great programming language in action. let see node.js do something cool by using socket.io to create live chat app with node.js plus I forgot to mention node doesn't need Apache server to work it has it own way of crating an HTTP connection.

Download Script Live Demo

What is Node.js all About?

Node.js is an asynchronous, event-driven framework built on top of Chrome's JavaScript engine and designed for creating scalable network applications. I was created with JavaScript plus a some of C/C++ under the hood so that it can do things like interacting with the filesystem, starting up HTTP or TCP and Socket servers and so on. It is non-blocking, so it doesn't make the program wait, but instead it registers a callback and lets the program continue. This means it can handle concurrent operations without multiple threads of execution, so it can scale pretty well.

How to Install Node.JS ?

Node.JS installation is easy, Visit Node.js Download Page to download the version compatible with your OS. Node.js also uses a package installer called npm but you do not need to worry, It is now embedded in the Node.JS package.
To test if Node.js is working Open your terminal and type node -v the version of node you have just installed should show up.

Server code.

Here is our server listening for connection at port 3000 on index.js file.
// Setup basic express server
var express = require('express');

var app = express();

var server = require('http').createServer(app);

var io = require('socket.io')(server);

var port = process.env.PORT || 3000;
server.listen(port, function () {
console.log('Server listening at port %d', port);
}
);
// Routing 
app.use(express.static(__dirname + '/public'));
// Chatroom
var numUsers = 0;
io.on('connection', function (socket) {
var addedUser = false;
// when the client emits 'new message', this listens and executes
socket.on('new message', function (data) {
// we tell the client to execute 'new message'
socket.broadcast.emit('new message', {
username: socket.username,
 message: data });
});
// when the client emits 'add user', this listens and executes 
socket.on('add user', function (username) {
if (addedUser) return;
// we store the username in the socket session for this client
socket.username = username;
++numUsers;
addedUser = true;
socket.emit('login', {
numUsers: numUsers }
);
// echo globally (all clients) that a person has connected 
socket.broadcast.emit('user joined', {
username: socket.username,
numUsers: numUsers });
});
// when the client emits 'typing', we broadcast it to others
socket.on('typing', function () {
socket.broadcast.emit('typing', {
username: socket.username }
);
}
);
// when the client emits 'stop typing', we broadcast it to others
socket.on('stop typing', function () {
socket.broadcast.emit('stop typing', {
username: socket.username });
});
// when the user disconnects.. perform this
socket.on('disconnect', function () {
if (addedUser) {
--numUsers;
// echo globally that this client has left
socket.broadcast.emit('user left', {
username: socket.username, numUsers: numUsers });
}
});
});

Client side code

Here is how our client is replaying our server code using the main.js.JQuery is used on the client side to help make our actions cross browser and secure.
$(function() {

var FADE_TIME = 150; // ms
var TYPING_TIMER_LENGTH = 400; // ms
var COLORS = [ '#e21400', '#91580f', '#f8a700', '#f78b00', '#58dc00', '#287b00', '#a8f07a', '#4ae8c4', '#3b88eb', '#3824aa', '#a700ff', '#d300e7' ];
// Initialize variables
var $window = $(window);

var $usernameInput = $('.usernameInput');
// Input for username
var $messages = $('.messages');
// Messages area
var $inputMessage = $('.inputMessage');
// Input message input box
var $loginPage = $('.login.page');
// The login page
var $chatPage = $('.chat.page');
// The chatroom page 

// Prompt for setting a username
var username;

var connected = false;

var typing = false;

var lastTypingTime;

var $currentInput = $usernameInput.focus();

var socket = io();
function addParticipantsMessage (data) {

var message = '';
if (data.numUsers === 1) {
message += "there's 1 participant";
} else {
message += "there are " + data.numUsers + " participants";
} log(message);
} // Sets the client's username function setUsername () {
username = cleanInput($usernameInput.val().trim());
// If the username is valid if (username) {
$loginPage.fadeOut();
$chatPage.show();
$loginPage.off('click');
$currentInput = $inputMessage.focus();
// Tell the server your username socket.emit('add user', username);
} } // Sends a chat message function sendMessage () {

var message = $inputMessage.val();
// Prevent markup from being injected into the message
 message = cleanInput(message);
// if there is a non-empty message and a socket connection 
 if (message && connected) {
$inputMessage.val('');
addChatMessage({
username: username, message: message });
// tell server to execute 'new message' and send along one parameter
socket.emit('new message', message);
} }
  // Log a message
 function log (message, options) {

var $el = $('<li>').addClass('log').text(message);
addMessageElement($el, options);
}
 // Adds the visual chat message to the message list
 function addChatMessage (data, options) {
// Don't fade the message in if there is an 'X was typing'
var $typingMessages = getTypingMessages(data);
options = options || {};
if ($typingMessages.length !== 0) {
options.fade = false;
$typingMessages.remove();
}
var $usernameDiv = $('<span class="username"/>') .text(data.username) .css('color', getUsernameColor(data.username));
var $messageBodyDiv = $('<span class="messageBody">') .text(data.message);

var typingClass = data.typing ? 'typing' : '';

var $messageDiv = $('<li class="message"/>') .data('username', data.username) .addClass(typingClass) .append($usernameDiv, $messageBodyDiv);
addMessageElement($messageDiv, options);
}
 // Adds the visual chat typing message 
 function addChatTyping (data) {
data.typing = true;
data.message = 'is typing';
addChatMessage(data);
}
 // Removes the visual chat typing message 
function removeChatTyping (data) {
getTypingMessages(data).fadeOut(function () {
$(this).remove();
});
}
 // Adds a message element to the messages and scrolls to the bottom 
// el - The element to add as a message
 // options.fade - If the element should fade-in (default = true) 
 // options.prepend - If the element should prepend 
 // all other messages (default = false) 

function addMessageElement (el, options) {

var $el = $(el);
// Setup default options
 if (!options) {
options = {
};
}
 if (typeof options.fade === 'undefined') {
options.fade = true;
}
 if (typeof options.prepend === 'undefined') {
options.prepend = false;
}
 // Apply options
 if (options.fade) {
$el.hide().fadeIn(FADE_TIME);
}
 if (options.prepend) {
$messages.prepend($el);
}
else {
$messages.append($el);
} $messages[0].scrollTop = $messages[0].scrollHeight;
}
 // Prevents input from having injected markup
function cleanInput (input) {
return $('<div/>').text(input).text();
}
 // Updates the typing event 
 function updateTyping () {
if (connected) {
if (!typing) {
typing = true;
socket.emit('typing');
} lastTypingTime = (new Date()).getTime();
setTimeout(function () {

var typingTimer = (new Date()).getTime();

var timeDiff = typingTimer - lastTypingTime;
if (timeDiff >= TYPING_TIMER_LENGTH && typing) {
socket.emit('stop typing');
typing = false;
} }, TYPING_TIMER_LENGTH);
} }
 // Gets the 'X is typing' messages of a user 
function getTypingMessages (data) {
return $('.typing.message').filter(function (i) {
return $(this).data('username') === data.username;
});
}
// Gets the color of a username through our hash function
 function getUsernameColor (username) {
// Compute hash code
var hash = 7;
for (var i = 0;i <username.length;i++) {
hash = username.charCodeAt(i) + (hash << 5) - hash;}
// Calculate color
var index = Math.abs(hash % COLORS.length);
return COLORS[index];
}
// Keyboard events
 $window.keydown(function (event) {
// Auto-focus the current input when a key is typed 
if (!(event.ctrlKey || event.metaKey || event.altKey)) {
$currentInput.focus();
}
 // When the client hits ENTER on their keyboard
 if (event.which === 13) {
if (username) {
sendMessage();
socket.emit('stop typing');
typing = false;
} else {
setUsername();
} } });
$inputMessage.on('input', function() {
updateTyping();
});
// Click events 
// Focus input when clicking anywhere on login page
 $loginPage.click(function () {
$currentInput.focus();
});
// Focus input when clicking on the message input's border 
 $inputMessage.click(function () {
$inputMessage.focus();
});
// Socket events 
// Whenever the server emits 'login', log the login message 
socket.on('login', function (data) {
connected = true;
// Display the welcome message
var message = "Welcome to Socket.IO Chat – ";
log(message, {prepend: true });
addParticipantsMessage(data);
});
// Whenever the server emits 'new message', update the chat body
socket.on('new message', function (data) {
addChatMessage(data);
});
// Whenever the server emits 'user joined', log it in the chat body 
socket.on('user joined', function (data) {
log(data.username + ' joined');
addParticipantsMessage(data);
});
// Whenever the server emits 'user left', log it in the chat body
socket.on('user left', function (data) {
log(data.username + ' left');
addParticipantsMessage(data);
removeChatTyping(data);
});
// Whenever the server emits 'typing', show the typing message
 socket.on('typing', function (data) {
addChatTyping(data);
});
// Whenever the server emits 'stop typing', kill the typing message 
 socket.on('stop typing', function (data) {
removeChatTyping(data);
});
});
To run the demo Open your Terminal navigate to the directory where the demo is located i.e. cd /wherever/chat/ Then type node index.js . After this you can now visit 127.0.0.1:3000 on your browser to access the demo.

Conclusion

Node isn't a silver bullet, but hopefully you have more insights on the proper use cases by now. In short, Node is a great option for applications that wait on I/O and have to handle a lot of concurrent connections.
Was this article helpful?
Thanks! Your feedback helps us improve tutorials.

You May Also Like...

No comments:

Post a Comment