I'm creating an application (chat app) and I'm pushing each username to an array. Using socket.io, whenever I call an event to push the username to the client side array, multiple instances of the array are created.
For example, the first user I log is fine, Then when another user is added, the array will double, then triple and so on. Thank you in advance for the help . The emit event in which I'm doing this is in the USERS_CONNECTED event.
I am also sorry for the terrible sloppiness of the code below.
Server
const express = require('express');
const fs = require('fs');
const path = require('path');
const http = require('http');
const socketIO = require('socket.io');
const publicPath = path.join(__dirname, 'public');
const port = process.env.PORT || 3001;
let app = express();
let server = http.createServer(app);
var io = socketIO(server);
let username;
app.use(express.static(publicPath));
let usersOnline = []; //keeps track of current users online
io.on('connection', (socket) => {
let user = socket.id;
socket.emit('user', user);
socket.id = "anon";
socket.on('new user', function(data,callback) {
//if user name is taken
if(usersOnline.indexOf(data) != -1 || data == ''){
callback(false);
}else{
//if username is not taken
callback(true);
socket.id = data;
username = data;
//pushes data(username) to data
usersOnline.push(socket.id);
//sends back to client usersOnline array
io.sockets.emit('USERS_CONNECTED', {usersOnline: usersOnline, user: socket.id});
console.log(usersOnline.length)
}
});
socket.on('disconnect', () => {
usersOnline.splice(usersOnline.indexOf(socket.id), 1);
//emits count users, sets current user
io.sockets.emit('USERS_CONNECTED', {usersOnline: usersOnline, user: socket.id});
console.log(usersOnline.length)
});
socket.on('send msg' , function(data){
io.sockets.emit('send msg', {msg: data, user: socket.id});
})
});
server.listen(port, () => {
console.log('server is running master')
});
Client
let socket = io();
let input = document.querySelector('#input_username');
let form = document.querySelector('form')
let userName_page = document.querySelector(".userName_page");
let chat_page = document.querySelector(".chat_page");
let chatWrapper = document.querySelector(".chat_wrapper")
let counter = document.getElementById("counter");
let users = document.querySelector(".users_online")
let join_btn = document.querySelector(".button-effect")
let msg_input = document.querySelector("#sendMsg");
let btn_send = document.querySelector("#send_btn");
let onlineUsers = [];
let sent_ = document.querySelector(".sent_");
let receive_ = document.querySelector(".receive_");
let newUser_text = document.querySelector(".welcome_box")
let user;
let isTyping = document.querySelector('#isTyping')
let welcome_header = document.querySelector("#welcome_header");
let users_online_container = document.querySelector(".users_online");
join_btn.addEventListener("click", function(e){
e.preventDefault();
user = input.value;
//sets user name to input.value
socket.emit('new user', input.value, function(data){
if(data){
userName_page.style.display = "none"
chat_page.style.display = "flex";
welcome_header.innerHTML = input.value + ' has joined the party';
addAnimation();
}else{
if(input.value == ''){
input.classList.add("input_error");
let error_msg = document.getElementById('error_input');
error_msg.innerHTML = '*Invalid, Please Type a Username'
error_msg.style.display = "block";
input.style.border = "2px solid #d9534f";
}else{
input.classList.add("input_error");
let error_msg = document.getElementById('error_input');
error_msg.style.display = "block";
error_msg.style.border = "2px solid #d9534f"
error_msg.innerHTML = "Woops, sorry but that user name is already taken, please try again";
}
}
});
//sets up new user
socket.on('USERS_CONNECTED' , function (data){
//counts online users currently
counter.innerHTML = (data.usersOnline.length + " Online");
for(let i = 0; i < data.usersOnline.length; i++){
onlineUsers.push(data.usersOnline);
let h = document.createElement("h3");
fish.appendChild(h);
}
console.log(onlineUsers)
});
});
//msg send
btn_send.addEventListener('click', function(){
socket.emit('send msg', msg_input.value);
});
//checks if enter is pressed, if so emits message to chat
function search(ele) {
if(event.key === 'Enter') {
socket.emit('send msg', msg_input.value);
}
}
//send message events
socket.on('send msg', function(data){
if(data.user == user){
//sender logic
msg_input.value = '';
let p = document.createElement('p');
receive_.append(p);
p.innerHTML = "<span class = 'er'>" + 'You' + "</span>" + ": " + data.msg;
p.style.textAlign = 'right';
p.style.backgroundColor = "#5cb85c";
p.style.justifyContent = "flex-end";
p.style.paddingRight = "2em";
}
else{
//receiver logic
msg_input.value = '';
let p = document.createElement('p');
receive_.append(p);
p.innerHTML = "<span class = 'er'>" + data.user + "</span>" + ": " + data.msg;
p.style.textAlign = 'left';
p.style.backgroundColor = "#5bc0de";
p.style.paddingLeft = "2em";
};
//makes sure scroll stays at bottom
receive_.scrollTop = receive_.scrollHeight;
});
function addAnimation(){
newUser_text.classList.add("act");
}
$( document ).ready(function(){
let header = document.querySelector(".feedback");
var timeout;
function timeoutFunction() {
typing = false;
socket.emit("typing", false);
}
$('#sendMsg').keyup(function() {
typing = true;
socket.emit('typing', 'typing...');
clearTimeout(timeout);
timeout = setTimeout(timeoutFunction, 5000);
});
socket.on('typing', function(data) {
if (data) {
$('#isTyping').html(data);
$('#isTyping').classList.add('act')
} else {
$('#isTyping').html("");
}
});
})
You should replace whole array on client side instead of push. Just stack trace your code:
Firstable on connection on server side you pushes new user id to usersOnline array and emits that array in object via USERS_CONNECTED event in usersOnline property. Client receives that object and pushes object of users (NOT exactly one new user) to onlineUsers array. So eg. 1 user connects to server, usersOnline array would be:
[ 'user1' ]
Then second user connects to server:
[ 'user1', 'user2' ]
And that array is being sent to user2, that is whole object sent by USERS_CONNECTED event would be:
{ usersOnline: [ 'user1', 'user2' ], user: 'user2' }
Now in client instead of replacing you are pushing whole new array, so instead [ 'user1', 'user2' ] you gets [ [ 'user1', 'user2' ] ]
Related
I'm creating a chat but I was inspired by a source, when I "Log-In" and the chat appears, this appears in the URL:
chat.html?username=rr&room=JavaScript
How do I make sure that when I enter the chat it simply sees "Chat.html"?
I tried to add this code to it, but the problem would be the same if someone changed, it's like it's a GET. How do I do it in POST? It doesn't come easy with javascript
Code:
const chatForm = document.getElementById('chat-form');
const chatMessages = document.querySelector('.chat-messages');
const roomName = document.getElementById('room-name');
const userList = document.getElementById('users');
// Get username and room from URL
const { username, room } = Qs.parse(location.search, {
ignoreQueryPrefix: true,
});
const socket = io();
socket.emit('joinRoom', { username, room });
socket.on('roomUsers', ({ room, users }) => {
outputRoomName(room);
outputUsers(users);
});
socket.on('message', (message) => {
console.log(message);
outputMessage(message);
chatMessages.scrollTop = chatMessages.scrollHeight;
});
chatForm.addEventListener('submit', (e) => {
e.preventDefault();
let msg = e.target.elements.msg.value;
msg = msg.trim();
if (!msg) {
return false;
}
socket.emit('chatMessage', msg);
// Clear input
e.target.elements.msg.value = '';
e.target.elements.msg.focus();
});
// Output message to DOM
function outputMessage(message) {
const div = document.createElement('div');
div.classList.add('message');
const p = document.createElement('p');
p.classList.add('meta');
p.innerText = message.username;
p.innerHTML += `<span> - ${message.time}</span>`;
div.appendChild(p);
const para = document.createElement('p');
para.classList.add('text');
para.innerText = message.text;
div.appendChild(para);
document.querySelector('.chat-messages').appendChild(div);
}
function outputRoomName(room) {
roomName.innerText = room;
}
function outputUsers(users) {
userList.innerHTML = '';
users.forEach((user) => {
const li = document.createElement('li');
li.innerText = user.username;
userList.appendChild(li);
});
}
document.getElementById('leave-btn').addEventListener('click', () => {
const leaveRoom = confirm('Sei sicuro di voler uscire dalla chatroom?');
if (leaveRoom) {
window.location = '../index.html';
} else {
}
});
I hope I have explained myself well, I just need to add security to the website because then they could enter random "rooms", could I put the sessions?
i am trying to do an message system (only conversation one user to one user) with mongoDB, node.js and socket.io all is working fine but when i send a message all the users receive it ... I will try to explain you better :
When 4 users are connected (2 in one chat and 2 other in an other chat)
User 1 : Chat a
User 2 : Chat a
User 3 : Chat b
User 4 : Chat b
When user 1 send a message : User 1, 2, 3, 4 see the message but only user 1 and 2 have the message save in database (so when i refresh all user : only user 1 and 2 have the message)
And here is the problem my messages are well saved but when someone send a message the socket send the message to all the users connected
Here is my code : server.js
var http = require('http');
var MongoClient = require('mongodb').MongoClient;
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'Database';
MongoClient.connect(url, function(err, client) {
if (err)
throw err;
console.log('MongoDB connected ...');
httpServer = http.createServer(function(req, res) {
console.log('This is a test');
res.end('Hello World');
});
httpServer.listen(1337);
var io = require('socket.io').listen(httpServer);
var users = {};
var messages = [];
io.sockets.on('connection', function (socket) {
const collection = client.db(dbName).collection('MessageUser');
var me = false;
var friend = false;
var conv = false;
for(var k in users) {
socket.emit('new_user', users[k]);
}
/**
* Login
*/
socket.on('login_chat', function (user) {
me = user;
friend = user.friend;
conv = user.conv;
console.log('New user : ', me.username, ' - id : ', me.id);
users[me.id] = me;
io.sockets.emit('new_user', me);
});
/**
* Disconnect
*/
socket.on('disconnect', function() {
if (!me) {
return false;
}
delete users[me.id];
io.sockets.emit('disc_user', me);
});
/**
* Message receive
*/
socket.on('new_msg', function(message){
if (message.message !== '') {
message.user = me;
date = new Date();
message.h = date.getHours();
message.m = date.getMinutes();
message.y = date.getFullYear();
message.m = date.getMonth();
message.d = date.getDate();
console.log(message);
messages.push(message);
msg = {};
msg.content = message.message;
msg.sendAt = new Date();
msg.idTransmitter = me.id;
msg.idReceiver = friend;
msg.idConversation = conv;
collection.insertOne(msg);
console.log(msg.idReceiver, msg.idTransmitter, me);
io.sockets.emit('new_msg', message, me, msg.idReceiver, msg.idTransmitter);
}
});
});
});
And client.js :
(function($){
var socket = io.connect('http://localhost:1337');
var lastmsg = false;
startTchat = function(user_id, username, friend_id, conv_id) {
socket.emit('login_chat', {
id : user_id,
username : username,
friend : friend_id,
conv : conv_id,
})
};
/**
* Error
*/
socket.on('error', function(err){
alert(err);
});
/**
* Messages
*/
$('#chat_form').submit(function(event){
event.preventDefault();
socket.emit('new_msg', {message: $('#message').val() });
$('#message').val('');
$('#message').focus();
});
socket.on('new_msg', function(message, me, id_receiver, id_transmiter){
if (me.id === id_receiver || me.id === id_transmiter) {
if (lastmsg != message.user.id) {
*(here i add a div with the msg)*
lastmsg = message.user.id;
} else {
*(here too)*
}
}
});
/**
* Login
*/
socket.on('new_user', function(user){
*(here i add a div with new user)*
});
/**
* Disconnect
*/
socket.on('disc_user', function(user){
$('#' + user.id).remove();
})
})(jQuery);
My idea was this line : if (me.id === id_receiver || me.id === id_transmiter) (client.js line 33) but that seems doing nothing ...
So should i add something or maybe my condition is not good ...
ps : That's one of my first time using node, js and socket so i hope i explain well and ask me if you need more info or screenshots maybe :)
After I authenticate to Firebase with Google auth, I get this console.log output and the JavaScript seems to bounce around in execution order. Here's my console output and the javascript code.
Why does "controller is: Pellet_Pirate_1" display at the log end rather than at the beginning where the code executes to pull this value from Firebase? My "GLOBAL CONTROLLER" and other logs of the contr global variable should be valued as well... I am trying to use contr as a global variable and it is defined at the top of my script tag
Any help would be greatly appreciated... I've banged my head on this one for many hours now!
console.log
<script type="text/javascript">
var contr = undefined;
function PelletPirate() {
this.userPic = document.getElementById('user-pic');
this.userName = document.getElementById('user-name');
this.signInButton = document.getElementById('sign-in');
this.signOutButton = document.getElementById('sign-out');
this.signOutButton.addEventListener('click', this.toggleSignOut.bind(this));
this.signInButton.addEventListener('click', this.toggleSignIn.bind(this));
this.initFirebase();
}
// Sets up shortcuts to Firebase features and initiate firebase auth.
PelletPirate.prototype.initFirebase = function() {
//FlymanEdit Shortcuts to Firebase SDK features.
this.auth = firebase.auth();
this.database = firebase.database();
this.storage = firebase.storage();
//FlymanEdit Initiates Firebase auth and listen to auth state changes.
this.auth.onAuthStateChanged(this.onAuthStateChanged.bind(this));
};
PelletPirate.prototype.toggleSignIn = function() {
var provider = new firebase.auth.GoogleAuthProvider(); // [Start createprovider]
provider.addScope('https://www.googleapis.com/auth/plus.login'); // [START addscopes]
this.auth.signInWithPopup(provider).then(function(result)
{
var token = result.credential.accessToken;
var user = result.user;
console.log('token: ' + token);
}).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
var email = error.email;
var credential = error.credential; // The firebase.auth.AuthCredential type that was used.
if (errorCode === 'auth/account-exists-with-different-credential') {
alert('You have already signed up with a different auth provider for that email.');
}
else {
console.error(error);
}
});
}
// Sign-out.
PelletPirate.prototype.toggleSignOut = function() {
this.auth.signOut();
console.log('******************** USER SIGNED OUT *********************');
};
PelletPirate.prototype.onAuthStateChanged = function(user) { // Triggers when user's auth state changes.
if (user) { // User is signed in!
// let's go fetch the Pellet Pirate controller name based on the logged in user!
console.log('user.uid is: ' + user.uid);
firebase.database().ref().child("owners").orderByChild("userId").equalTo(user.uid).on('value', function (snapshot) {
snapshot.forEach(function(childSnapshot) {
contr = childSnapshot.val().controller;
//MYLIBRARY.init([controller, 1, "controller"]);
//MYLIBRARY.passVar();
console.log('controller is: ' + contr);
return contr;
});
});
var currentDate = new Date();
var profilePicUrl = user.photoURL;
var userName = user.displayName;
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var refreshToken = user.refreshToken;
var providerData = user.providerData;
//console.log('You have signed in: ' + userName );
console.log('*************** signed in: ' + userName + ' *****************');
console.log('GLOBAL CONTROLLER: ' + contr);
document.getElementById('authed').style.visibility = 'visible';
document.getElementById('authed2').style.visibility = 'visible';
document.getElementById('gauges').style.visibility = 'visible';
document.getElementById('graph').style.visibility = 'visible';
document.getElementById('parameters').style.visibility = 'visible';
document.getElementById('ParmForm').style.visibility = 'visible';
document.getElementById('ClearDataButton').style.visibility = 'visible';
document.getElementById('AddProgramButton').style.visibility = 'visible';
document.getElementById('programrows').style.visibility = 'visible';
// Set the user's profile pic and name.
this.userPic.style.backgroundImage = 'url(' + profilePicUrl + ')';
this.userName.textContent = userName;
// Show user's profile and sign-out button.
this.userName.removeAttribute('hidden');
this.userPic.removeAttribute('hidden');
this.signOutButton.removeAttribute('hidden');
// Hide sign-in button.
this.signInButton.setAttribute('hidden', 'true');
console.log('before firebase controller is: ' + contr);
//controllerName = "Pellet_Pirate_1";
//Firebase
var TempsRef = Ref.child('ControllerData/' + contr + '/Temps');
console.log('after firebase controller is: ' + contr);
TempsRef.limitToLast(3600/3*16).once("value", function(snapshot) { //Limit to last 16 hours
var Ts = snapshot.val();
for (var k in Ts) {
T1.push([Ts[k].time, Ts[k].T1]);
T2.push([Ts[k].time, Ts[k].T2]);
T3.push([Ts[k].time, Ts[k].T3]);
TT.push([Ts[k].time, Ts[k].TT]);
console.log('in snapshot');
}
TempsRef.limitToLast(1).on("child_added", function(snapshot, prevChildKey) { //Establish callback
var Ts = snapshot.val();
T1.push([Ts.time, Ts.T1]);
T2.push([Ts.time, Ts.T2]);
T3.push([Ts.time, Ts.T3]);
TT.push([Ts.time, Ts.TT]);
UpdatePlot();
console.log('in snapshot-previousChildKey' );
//console.log('in snapshot-PCK-controllerName is:' + controllerName);
});
UpdatePlot();
});
TempsRef.on("child_removed", function(snapshot, prevChildKey) {
T1 = [];
T2 = [];
T3 = [];
TT = [] ;
UpdatePlot();
});
}
else { // User is signed out!
// Hide user's profile and sign-out button.
this.userName.setAttribute('hidden', 'true');
this.userPic.setAttribute('hidden', 'true');
this.signOutButton.setAttribute('hidden', 'true');
document.getElementById('authed').style.visibility = 'hidden';
document.getElementById('authed2').style.visibility = 'hidden';
document.getElementById('gauges').style.visibility = 'hidden';
document.getElementById('graph').style.visibility = 'hidden';
document.getElementById('parameters').style.visibility = 'hidden';
document.getElementById('ParmForm').style.visibility = 'hidden';
document.getElementById('ClearDataButton').style.visibility = 'hidden';
document.getElementById('AddProgramButton').style.visibility = 'hidden';
document.getElementById('programrows').style.visibility = 'hidden';
// Show sign-in button.
this.signInButton.removeAttribute('hidden');
// undefine the controller
contr = undefined;
}
}; // [ END onAuthStateChanged - auth state listener]
Because on() is asynchronous. It returns immediately while the query is happening in the background. Meanwhile, the code immediately after that runs until the first time the callback you provided to it is invokes with a snapshot of results.
When I try to send a message within a room I get this TypeError: Cannot read property roomClients' of undefined,
node.js and working with sockets is new to me, so the fix might be simple.
Any idea to what causes the error? I really appreciate any suggestions
Here is the server-side code:
// Setting up the server
var express = require('express');
var app = express();
var path = require('path');
var server = require('http').createServer(app);
var socket = require("socket.io").listen(server);
var Room = require('./room.js');
var _ = require('underscore')._;
var uuid = require ('uuid');
server.listen(process.env.PORT || 3000);
console.log('Server is running...');
socket.set("log level", 1);
var people = {};
var rooms = {};
var clients = [];
Array.prototype.contains = function(k, callback) {
var self = this;
return (function check(i) {
if (i >= self.length) {
return callback(false);
}
if (self[i] === k) {
return callback(true);
}
return process.nextTick(check.bind(null, i+1));
}(0));
};
// Gets the html file
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
})
// Gets the css file
app.use(express.static(path.join(__dirname, 'public')));
// When connecting
socket.on("connection", function(client) {
client.on("join", function(name){
console.log("Someone joined the chat", name);
roomID = null;
people[client.id] = {"name" : name, "room" : roomID};
sizePeople = _.size(people);
sizeRooms = _.size(rooms);
socket.sockets.emit("update-people", {people: people, count: sizePeople});
socket.sockets.emit("roomList", {rooms: rooms, count: sizeRooms});
client.emit("updateToSelf", "You have connected to the server. Join or create room to chat");
client.broadcast.emit('updateToOthers', name + " is online.");
//client.emit("roomList", {rooms: rooms});
clients.push(client); //populate the clients array with the client object
});
//Creating room
client.on("serverCreateNewRoom", function(name){
console.log("About to create a room", name)
if (people[client.id].room === null) {
console.log("First time creating a room")
var id = uuid.v4();
var room = new Room(name, id, client.id);
rooms[id] = room;
sizeRooms = _.size(rooms);
socket.sockets.emit("roomList", {rooms: rooms, count: sizeRooms}); //update the list of rooms on the frontend
client.room = name; //name the room
client.join(client.room); //auto-join the creator to the room
room.addPerson(client.id); //also add the person to the room object
people[client.id].room = id; //Update the room key with the ID of the created room
client.emit("updateToSelf", "You have created a room");
} else {
socket.sockets.emit("updateToSelf", "You have already created a room");
}
});
//joining room
client.on("joinRoom", function(id) {
console.log("Someone is trying to join a room")
var room = rooms[id];
if (client.id === room.owner) {
client.emit("updateToSelf", "You are the owner of this room and you have already been joined.");
console.log("Owner is trying to join own room");
} else {
room.people.contains(client.id, function(found) {
if (found) {
client.emit("updateToSelf", "You have already joined this room.");
} else {
if (people[client.id].inroom !== null) { //make sure that one person joins one room at a time
client.emit("updateToSelf", "You are already in a room ("+rooms[people[client.id].inroom].name+"), please leave it first to join another room.");
console.log("User is already in the room");
} else {
room.addPerson(client.id);
people[client.id].inroom = id;
client.room = room.name;
client.join(client.room); //add person to the room
user = people[client.id];
socket.sockets.in(client.room).emit("updateToOthers", user.name + " has connected to " + room.name + " room.");
client.emit("update", "Welcome to " + room.name + ".");
client.emit("sendRoomID", {id: id});
}
}
});
}
});
// When sending
client.on("send message", function(msg){
if (socket.sockets.manager.roomClients[socket.id]['/'+socket.room] !== undefined) {
socket.sockets.in(client.room).emit("chat", people[client.id], msg);
//client.emit("ownMessage", msg);
//client.broadcast.emit('newMessageToOthers', people[client.id], msg);
console.log("Message send", msg);
} else {
client("updateToSelf", "Please connect to a room");
}
});
});
I am trying to learn node JS and am currently attempting to extend this article.
http://www.gianlucaguarini.com/blog/push-notification-server-streaming-on-a-mysql-database/
I am having major issue because I am getting multiple updates in the SQL query.
I only want to send one socket update.
This issue is in the transactions loop I get multiple socket updates.
I have been struggling with this for over a month and can't seem to figure it out on my own (or with google searches)
Can someone please tell me how I can make this work so I only get one socket update per client.
What I would like to happen is when there is a change in one of the transactions that the two parties (buyer and seller) are the only ones that get the socket update.
How can I make this work? It is so close to what I want it do but I can't get over this last challenge.
Please help.
Thank you in advance.
<html>
<head>
<title>GAT UPDATER</title>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script src = "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script type="text/javascript" src="http://board.gameassettrading.com/js/jquery.cookie.js"></script>
</head>
<body>
<script>
var nodeuserid;
function getUserId() {
var url = window.location.href;
var user_id = url.replace('http://heartbeat.gameassettrading.com:4000/id/', '');
return user_id;
}
user_id = getUserId();
$.cookie('useridcookie', user_id, { expires: 1 });
var useridcookie = $.cookie("useridcookie");
// Get Base Url for development between local and dev enviroment
function getBaseURL() {
var url = location.href; // entire url including querystring - also: window.location.href;
var baseURL = url.substring(0, url.indexOf('/', 14));
if (baseURL.indexOf('http://localhost') != -1) {
// Base Url for localhost
var url = location.href; // window.location.href;
var pathname = location.pathname; // window.location.pathname;
var index1 = url.indexOf(pathname);
var index2 = url.indexOf("/", index1 + 1);
var baseLocalUrl = url.substr(0, index2);
return baseLocalUrl + "/";
}
else {
// Root Url for domain name
return baseURL + "/";
}
}
// set the base_url variable
base_url = getBaseURL();
document.domain = "transactionsserver.com"
// create a new websocket
var socket = io.connect('http://heartbeat.transactionsserver.com:4000');
socket.on('connect',function() {
var data = {
url: window.location.href,
};
socket.emit('client-data', data);
});
// this is always open you have to filter out the data you want
socket.on('notification', function (data) {
if(data.hasOwnProperty("data")) {
if(data.data[0]['seller_id'] != ''){
$('#StatusUpdate', window.parent.document).text( data.data[0]['seller_id']+ ':' + data.data[0]['seller_status'] +':'+ data.data[0]['buyer_id']+':'+ data.data[0]['buyer_status']).click();
}
}
window.parent.checkData(data,user_id);
if(data.hasOwnProperty("changed_user_id")) {
$('#StatusUpdate', window.parent.document).text( data.changed_user_id+ ':' + data.changed_user_status +':'+ data.changed_user_id).click();
}
});
</script>
</body>
</html>
Server . js
var app = require("express")();
var path = require('path');
var mysql = require("mysql");
var http = require('http').Server(app);
var io = require("socket.io")(http);
var sockets = {};
var mysql = require('mysql'),
connectionsArray = [],
connection = mysql.createConnection({
multipleStatements: true,
host: 'localhost',
user: '*****',
password: '******',
database: 'transactionsdb',
port: 3306
}),
POLLING_INTERVAL = 1000,
pollingTimer;
// Add Redis For Comparing SQL Results againts Cache
var redis = require('redis');
var client = redis.createClient();
var express = require('express');
/* Creating POOL MySQL connection.*/
var pool = mysql.createPool({
connectionLimit: 100,
host: 'localhost',
user: '*****',
password: '*****',
database: 'transactionsdb',
debug: false
});
var count = 0;
var clients = [];
function processAllTransactions(sellsreply) {
pool.query('SELECT t.id,t.status,t.original_status, t.active, t.buyer_id, t.seller_id, t.seller_acked, t.seller_complete, t.buyer_complete, b.user_status as buyer_status,t.chat_ended, s.user_status as seller_status FROM transaction t LEFT JOIN sf_guard_user_profile s ON s.user_id = t.seller_id LEFT JOIN sf_guard_user_profile b ON b.user_id = t.buyer_id WHERE active = 1 LIMIT 1', [sellsreply], function (err, sells) {
if (sells != '') {
// attempt to stop the updates if it's not the the active transaction
client.get('active transaction id:'+sellsreply, function (err, active_transaction_id) {
passed_active_transaction_id = active_transaction_id;
});
// is there a trasnaction with status defined and transation id does not equal the active transaction id
if(sells[0].status !== undefined && sells[0].id !== passed_active_transaction_id )
{
client.get('active transaction:'+sellsreply, function (err, data1) {
if(JSON.stringify(sells) != data1){
client.set('active transaction id:'+sellsreply,sells[0]["id"]);
client.set('active transaction:'+sellsreply,JSON.stringify(sells));
console.log(JSON.stringify(sells));
updateSockets({
data: sells // pass the database result
});
}
});
}
}
});
}
// Method
function getUserInfo(user_id, callback) {
var query = connection.query('SELECT user_status from sf_guard_user_profile WHERE user_id = ' + connection.escape(user_id));
query.on('result', function (row) {
callback(null, row.user_status);
});
}
var updateSockets = function (data) {
// adding the time of the last update
data.time = new Date();
console.log('Pushing new data to the clients connected ( connections amount = %s ) - %s', connectionsArray.length , data.time);
// sending new data to all the sockets connected
connectionsArray.forEach(function (tmpSocket) {
console.log(tmpSocket);
tmpSocket.volatile.emit('notification', data);
});
};
var pollingLoop = function () {
var socket;
for (var id in sockets) {
socket = sockets[id];
client.get("uuid:" + socket.id, function (err, useridreply) {
processAllTransactions(useridreply);
});
}
connection.query('SELECT * FROM sf_guard_user_profile; select * FROM transaction', function (err, result) {
// error check
if (err) {
console.log(err);
updateSockets(err);
throw err;
} else {
// loop through the queries
var element =
// compare the cache results againt the database query for users
result[0].forEach(function (element, index, array) {
client.get('logged_in:' + element.user_id, function (err, reply) {
if (reply === null) {
// console.log( element.user_id + ' is disconnected');
}
else {
// console.log(reply);
}
});
client.get("user:" + element.user_id, function (err, userreply) {
if (element.user_status != userreply) {
client.set('user:' + element.user_id, +element.user_status);
changed_users.push(element);
console.log(element.user_id + " is now set to: " + element.user_status);
updateSockets({
changed_user_id: element.user_id,
changed_user_status: element.user_status
});
}
});
});
}
// loop on itself only if there are sockets still connected
if (connectionsArray.length) {
pollingTimer = setTimeout(pollingLoop, POLLING_INTERVAL);
// reset changed users and changed transactions arrays
changed_users = [];
changed_transactions = [];
} else {
console.log('The server timer was stopped because there are no more socket connections on the app');
}
});
};
// count the connections array
Array.prototype.contains = function (k, callback) {
var self = this;
return (function check(i) {
if (i >= self.length) {
return callback(false);
}
if (self[i] === k) {
return callback(true);
}
return process.nextTick(check.bind(null, i + 1));
}(0));
};
io.sockets.on('connection', function (socket) {
// runs for every connection
sockets[socket.id] = socket;
socket.on('client-data', function (data) {
// get the user id from the url that is passed onload
var user_id = data.url.replace('http://servernameremoved.com:4000/id/', '');
console.log('user id ' + user_id + ' is connected with session id ' + socket.id);
client.set('uuid:' + socket.id, +user_id);
});
console.log('Number of connections:' + (connectionsArray.length));
// starting the loop only if at least there is one user connected
if (!connectionsArray.length) {
pollingLoop();
}
socket.on('disconnect', function (socketIndex) {
delete sockets[socket.id];
client.get("uuid:" + socket.id, function (err, userreply) {
console.log('user id ' + userreply + ' got redis disconnected');
});
socketIndex = connectionsArray.indexOf(socket);
console.log('socketID = %s got disconnected', socketIndex);
if (~socketIndex) {
connectionsArray.splice(socketIndex, 1);
}
});
connectionsArray.push(socket);
});
// express js route
app.get('/id/:id', function (req, res) {
clients.contains(req.params.id, function (found) {
if (found) {
console.log("Found");
} else {
client.set('logged_in:' + req.params.id, +req.params.id + 'is logged in');
}
});
res.sendFile(__dirname + '/client.html');
});
// build the server
http.listen(4000, function () {
console.log("Server Started");
});
Here is the console log results
Pushing new data to the clients connected ( connections amount = 2 ) - Sat May 30 2015 21:16:23 GMT-0700 (PDT)
30 2015 21:15:15 GMT-0700 (PDT)
user id 3 is connected with session id CRTtkRIl7ihQ2yaEAAAA
user id 2 is connected with session id wNG7XDcEDjhYKBEIAAAB
***********************************************
[{"id":1,"status":20,"original_status":15,"active":1,"buyer_id":2,"seller_id":1,"seller_acked":1,"seller_complete":0,"buyer_complete":1,"buyer_status":4,"chat_ended":"2015-05-31T03:58:40.000Z","seller_status":4}]
***********************************************
Pushing new data to the clients connected ( connections amount = 2 ) - Sat May 30 2015 21:16:23 GMT-0700 (PDT)
***********************************************
[{"id":1,"status":20,"original_status":15,"active":1,"buyer_id":2,"seller_id":1,"seller_acked":1,"seller_complete":0,"buyer_complete":1,"buyer_status":4,"chat_ended":"2015-05-31T03:58:40.000Z","seller_status":4}]
***********************************************
Pushing new data to the clients connected ( connections amount = 2 ) - Sat May 30 2015 21:16:23 GMT-0700 (PDT)