I had created a database connection and fetched the data from db on serverside. How can i pass my data from serverside to client side javascript in node.js. please help me out i had read many google searchs but didn't find any helpful stuff.
I'm using Emitter for my events. Now it is working on serverside my i can't able to pass the data to client side.
this is my code:
var dbrows;
// Connecting to Database.
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : ''
});
var DBName = 'use ChatDB';
connection.connect();
connection.query(DBName);
connection.query('SELECT * from chat', function(err, rows, fields) {
if (err) throw err;
dbrows = rows;
});
connection.end();
// Event Emitter emits out pre-defined events.
var EventEmitter = require("events").EventEmitter;
var Emitter = new EventEmitter();
Emitter.on('ChatUsers', function () {
console.log(dbrows);
});
If you don't have to use Emitter, i suggest you to use a WebSocket library like socket.io. It is simple to use. For your code, you can write something like this:
io.on('connection', function (socket) {
socket.on('sendUsers', function (data) {
connection.connect();
connection.query(DBName);
connection.query('SELECT * from chat', function(err, rows, fields) {
if (err) throw err;
socket.emit('sendUsers', rows);
});
connection.end();
});
});
and on client side:
socket.on('sendUsers', function(data){
console.log(data); // here you have your db records.
});
More info and examples here:
Socket.io
here is the server side code:
// This file is required by app.js. It sets up event listeners
// for the two main URL endpoints of the application - /create and /chat/:id
// and listens for socket.io messages.
// Use the gravatar module, to turn email addresses into avatar images:
var gravatar = require('gravatar');
// Export a function, so that we can pass
// the app and io instances from the app.js file:
module.exports = function(app,io){
app.get('/', function(req, res){
// Render views/home.html
res.render('home');
});
app.get('/create', function(req,res){
// Generate unique id for the room
var id = Math.round((Math.random() * 1000000));
// Redirect to the random room
res.redirect('/chat/'+id);
});
app.get('/chat/:id', function(req,res){
// Render the chat.html view
res.render('chat');
Emitter.emit('ChatUsers');
});
// Initialize a new socket.io application, named 'chat'
var chat = io.of('/socket').on('connection', function (socket) {
// When the client emits the 'load' event, reply with the
// number of people in this chat room
socket.on('load',function(data){
if(chat.clients(data).length === 0 ) {
socket.emit('peopleinchat', {number: 0});
Emitter.emit("ChatUsers");
}
else {
socket.emit('peopleinchat', {
number: 1,
user: chat.clients(data)[0].username,
avatar: chat.clients(data)[0].avatar,
id: data
});
}
});
// THIS IS YOUR CODE WHAT YOU WROTE FOR ME:
socket.on('sendUsers', function (data) {
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
});
var DBName = 'use ChatDB';
connection.connect();
connection.query(DBName);
connection.query('SELECT * from chat', function(err, rows, fields) {
if (err) throw err;
socket.emit('sendUsers', rows);
});
connection.end();
});
// When the client emits 'login', save his name and avatar,
// and add them to the room
socket.on('login', function(data) {
console.log(data);
// Use the socket object to store data. Each client gets
// their own unique socket object
socket.username = data.user;
socket.room = data.id;
socket.avatar = gravatar.url(data.avatar, {s: '140', r: 'x', d: 'mm'});
// Tell the person what he should use for an avatar
socket.emit('img', socket.avatar);
// Add the client to the room
socket.join(data.id);
if(chat.clients(data.id).length >= 2 ) {
console.log(data.id);
var usernames = [],
avatars = [];
usernames.push(chat.clients(data.id)[0].username);
usernames.push(chat.clients(data.id)[1].username);
avatars.push(chat.clients(data.id)[0].avatar);
avatars.push(chat.clients(data.id)[1].avatar);
// Send the startChat event to all the people in the
// room, along with a list of people that are in it.
chat.in(data.id).emit('startChat', {
boolean: true,
id: data.id,
users: usernames,
avatars: avatars
});
}
});
// Somebody left the chat
socket.on('disconnect', function() {
// Notify the other person in the chat room
// that his partner has left
socket.broadcast.to(this.room).emit('leave', {
boolean: true,
room: this.room,
user: this.username,
avatar: this.avatar
});
// leave the room
socket.leave(socket.room);
});
// Handle the sending of messages
socket.on('msg', function(data){
// When the server receives a message, it sends it to the other person in the room.
socket.broadcast.to(socket.room).emit('receive', {msg: data.msg, user: data.user, img: data.img});
});
});
};
Related
I'm new in node js and socket io, I'm trying to create interactive quizzes based on pin code given in the url for ex: http://domain/start/5555 should create a quiz page with name 5555 and when clients have the pin code they can connect to this quiz. So it means i have to have a quiz page which shows all connected clients for example but i have some prblems with io.sockets.in(pincode).emit()
because i don't know if i'm creating rooms correctly or not!
here is my code
Client.js
var socket = io();
socket.on('connect', function () {
var params = jQuery.deparam(window.location.search);// To get the name and the room
socket.emit('join', params, function (err) {
if (err) {
alert(err);
window.location.href = '/join.html';
} else {
console.log('No error');
}
});
});
Server.js
app.get('/start/:pincode', (req, res) => {
io.on('connection', (socket) => { // to rigester connection listener
console.log('New user is connected');
// When somebody connects it verifies if the name and the room are valid strings
socket.on('join', (params, callback) => {
if (!isRealSrting(params.name) || !isRealSrting(params.pincode)) {
return callback('Name and pincode are required');
}
socket.join(params.pincode);
users.removeUser(socket.id);//Remove the user from other places
users.addUser(socket.id, params.name, params.pincode);
var x = users.getUserList(params.pincode);
console.log(x);
io.sockets.in(params.pincode).emit('updateUserList', { //here it doesn't work i don't know why!
users: users.getUserList(params.pincode),
pincode: params.pincode
});
socket.emit('newMessage', {
user: params.name,
pincode: params.pincode,
readyMessage: 'You are connected'
});// when the user connect to the server he gets this message
callback();
});
socket.on('disconnect', () => {
var user = users.removeUser(socket.id);
if (user) {
io.emit('updateUserList', users.getUserList(user.pincode));
//io.to(user.room).emit('newMessage', generateMessage('Admin', `${user.name} has left`));
}
});
});
res.render('start.hbs', {
pincode: req.params.pincode
});
});
and the main page
Start.js
var socket = io();
var pincode;
socket.on('updateUserList', function (users) {
console.log('here');
var ol = jQuery('<ol></ol>');
var usercount = users.users.length; // Players number
pincode = users.pincode;
});
Any help or suggestion please?
I want to be able to load these 4 functions: returnAvailable, processMessage, removeUser and joinRoom from an external file, but i get reference errors where it says that socket and nicknames are undefined. How do I modularize my app with respect to dependencies I use?
Here's my code:
server.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
// mongoDB init
var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost:27017/chat");
var Message = require('./server/datasets/message');
//include these 4 functions
var util = require('./server/util/util');
//object which contains all users and chatrooms
var nicknames = {
'Music': [],
'Videogames': [],
'Sports': [],
'TV': [],
'Politics': []
};
// middleware
// serves static files
app.use('/client', express.static(__dirname + '/client'));
app.use('/node_modules', express.static(__dirname + '/node_modules'));
// routes
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html')
});
app.get('/api/rooms/get', function(req, res){
res.json(nicknames);
});
server.listen(2000);
// socket functionality
io.sockets.on('connection', function(socket){
socket.on('new user', util.returnAvailable);
// do when 'send message' data is received from client
socket.on('send message', function(data){
util.processMessage(data);
});
// do when 'disconnect' data is received from the client
socket.on('disconnect', function(data){
util.removeUser();
});
socket.on('leave room', function(){
util.removeUser();
});
});
util.js
module.exports.returnAvailable = function (data, callback){
console.log(data);
if(nicknames[data.room].indexOf(data.username) != -1){
callback({ bool: false });
}else {
socket.nickname = data.username;
joinRoom(socket, data.room);
nicknames[data.room].push(socket.nickname);
console.log(nicknames[data.room]);
io.sockets.to(data.room).emit('usernames', nicknames[data.room]);
callback({ bool: true, nickname: socket.nickname});
}
}
module.exports.removeUser = function(){
//console.log(socket.nickname + " disconnected. Bool value: " + socket.nickname==true);
if(socket.nickname==false) return;
// socket.room has to be defined, otherwise crashes if user reloads while not in a roomn
if(socket.room)
{
nicknames[socket.room].splice(nicknames[socket.room].indexOf(socket.nickname), 1);
socket.leave(socket.room);
}
io.sockets.to(socket.room).emit('usernames', nicknames[socket.room]);
}
module.exports.joinRoom = function (data){
socket.join(data);
socket.room = data;
console.log(socket.room);
var query = Message.find({room: socket.room});
query.sort({created:-1}).limit(5).exec(function(err, results){
if(err) { console.log(err); }
else if(results){
io.sockets.to(socket.room).emit('old messages', results);
}
});
}
module.exports.processMessage = function(data){
io.sockets.to(socket.room).emit('new message', {msg : data, nick : socket.nickname});
var message = new Message({
created: new Date,
user: socket.nickname,
message: data,
room: socket.room
});
message.save(function(err){
if(err){
console.log(err);
}else{
console.log('Successfully saved.');
}
});
}
I'm using Express 4.13.4
The socket variable is only available within io.sockets.on('connection', callback function so you can't use it in other files this easily. But you can pass the socket variable to the function where you are trying to use it like this
util.removeUser(socket);
and change the definition of removeUser to accept the socket as an argument
module.exports.removeUser = function(socket){
// your code here
}
The same goes for nicknames variable, use it like this
socket.on('new user', function(data) {
util.returnAvailable(io, socket, nicknames, data);
});
and change the function to accept those arguments
module.exports.returnAvailable = function (io, socket, nicknames, data){
// your code here
}
I'm working on chat, where facebook friends can talk only with each other. I'm using redis so save relation: fb_user_id - user_socket_id. This is how my implementation looks like:
getting friends from facebook;
selecting socket ids of my friends from redis, creating local friends-sockets list in my node client;
connecting to node server. Server saving my socket id to redis and notifying all my friends about new friend login (about me);
all my friends updating local friends-sockets list;
when someone sending chat message to server, this message comes with friends-sockets list, so server knows where need to send message (only for my friends).
Question: it's better solution to send friends-sockets every time to server, or it's better to get this relation on server from redis (or create array of sockets in server). How to adapt my task for high availability?
Any comments and suggestions are welcomed, thanks.
Here is my code (socket.io 1.2.0)
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var redis = require("redis"), client = redis.createClient();
var parts;
client.select(2, function() {});
client.on("error", function (err) {
console.log("Error " + err);
});
process.on('uncaughtException', function (err) {
console.log(err);
});
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
// on connect
socket.on("join", function (data)
{
if (data) {
// notify all friedns about new friend login
if (data.to) {
if (data.to.length > 0) {
for (x in data.to) {
io.to(data.to[x]['socket_id']).emit('new friend response', {uid: data.uid, sid: socket.id});
}
}
}
// save or update user socket id to redis
parts = split_id(data.uid);
client.hset(parts[1], parts[0], socket.id);
}
});
// disconnect
socket.on('disconnect', function () {
console.log("user disconnected");
});
// send message by friends-sockets list
socket.on('chat message', function (data) {
if (data.to.length > 0) {
for (x in data.to) {
var message = data.msg;
io.to(data.to[x]['socket_id']).emit('chat message response', {msg: message, uid: data.uid});
}
}
});
});
http.listen(3000, function () {
console.log('listening on *:3000');
});
// split facebook uid in 2 parts (for redis saving)
function split_id(str)
{
var n = str.length;
var res1 = str.substr(n - 2, 2);
var res2 = str.substr(0, n - 2);
return [res1, res2];
}
client.js
// friends socket list
var friends_sockets = [];
// my data from facebook
var my_data;
// my facebook uid
var my_uid;
function client() {
socket = io('http://server.com:3000');
// connect
socket.on('connect', function () {
// notify server about login
socket.emit('join', {uid: my_uid, to: friends_sockets, from: my_data, type: 'web'});
});
// send chat message to my friends
$('.enter_form button').click(function () {
if (friends_sockets.length > 0) {
socket.emit('chat message', {msg: $('#m').val(), to: friends_sockets, from: my_data, uid: my_uid});
}
// add message to my chat
$('#messages').append($('<li>').text(my_data.first_name + ' ' + my_data.last_name + ': ' + $('#m').val()));
$('#m').val('');
return false;
});
// new message listner (waiting for chat messages)
socket.on('chat message response', function (data) {
$('#messages').append($('<li>').text(data.msg));
});
// new friends lister (update list on friends login)
socket.on('new friend response', function (data) {
var found = false;
if (friends_sockets.length > 0) {
for (x in friends_sockets) {
if (friends_sockets[x]['uid'] == data.uid) {
friends_sockets[x]['socket_id'] = data.sid;
found = true;
}
}
}
if (found === false) {
friends_sockets.push(data);
}
});
}
Concerning your question regarding high availablity, have a look at
http://socket.io/docs/using-multiple-nodes/
for a configuration example using nginx, multiple Node processes and Redis as session store.
Following is the code on front end, where storeSelUserId contains user_id to send the message-
FYI - Node Version 1.1.0
// Socket Notification
var socket = io('http://localhost:6868');
socket.on('connection', function (data) {
socket.emit('send notification', { sent_to: storeSelUserId });
});
Following is the server code in routes file -
var clients = {};
io.on('connection', function (socket) {
socket.emit('connection', "Connection Created.");
socket.on('send notification', function (sent_to) {
console.log(sent_to);
});
});
In console sent_to is showing the array of user_id.
Now being a starter in socket.io I stuck with the solution that how do I send the message to these particular userids.
I search and found that I need to push each user with its sockets so I reformed it to -
var users = [];
io.on('connection', function (socket) {
users.push({socket_id: socket.id});
socket.emit('connection', "Connection Created.");
socket.on('send notification', function (sent_to) {
console.log(sent_to);
});
});
But I am in dilemma that else do I need to do to store which user_id refers to which socket_id and then update the div of users with that particular ids?
EDIT -
Add Controller - (Front End)
Front end Interface where memo is created and send to particular users
var socket = io('http://localhost:6868');
socket.on('connection', function (data) {
socket.emit('send memo notification', {creator_id: creator_id, sent_to: [Array of user_ids to whom memo to send]});
});
Dashboard controller - (Front End)
Front end Interface where notification count to show "notificationCount"
if (SessionService.currentUser._id) {
var socket = io('http://localhost:6868');
socket.on('connection', function (data) {
socket.emit('get notifications', {user_id: SessionService.currentUser._id});
});
socket.on('notification data', function(data){
console.log("-- Not Data Test -");
$scope.notificationCount = data.length;
});
}
Code at server end -
io.on('connection', function (socket) {
socket.emit('connection', "Connection Created.");
socket.on('send memo notification', function(data) {
notifications.createNotification(data);
});
socket.on('get notifications', function(data){
notifications.getNotifications(data, function(response){
socket.emit('notification data', response.data);
});
});
});
Backend controller code -
exports.getNotifications = function(data, callback) {
var userId = data.user_id;
Notification.find({receiver_id: userId}, function(err, response){
if (err)
callback({"message": "error", "data": err, "status_code": "500"});
else
callback({"message": "success", "data": response, "status_code": "200"});
});
};
exports.createNotification = function(data) {
var notificationData = data;
var x = 0;
for(var i=0; i< notificationData.length; i++) {
// Code
Notification(notificationData[i]).save(function(err,response){
if (err)
return false;
});
if (x === notificationData.length - 1) {
return true;
}
x++;
}
};
If you want to use your own user ids then there is no way around mapping the socket id to the user id. I assume a client knows its user id from somewhere, so it could send its user id to the server after connection.
Client
socket.on('connection', function (data) {
socket.emit('setUserId', myUserId);
});
The server saves the socket for each user id.
socket.on('setUserId', function (userId) {
users[userId]=socket;
});
If you have such a mapping in the server you can send a message just to this client using the user id.
socket.on('send notification', function (userId) {
users[userId].emit('notification', "important notification message");
});
Edit: Saving the corresponding socket directly is even better.
According to what i understand, you need private notification send to only some users. For that, save your users name to whom you want to send and their corresponding socket in different hashes.
username [socket.name] = username to be added;
usersocket [ socket.name ] =socket;
Then to emit the messages to that user only, use
usersocket[ socket.name ].emit('event for send message', ' what you want to send ');
am working on push notifications using mongodb and nodejs.
I can see the newly added notifications (which are addede in Mongodb) in my browser
But, if I updated the record, the value is not updating in the browser
// if no error get reference to colelction named: 'notifications'
db.collection('notifications', function(err, collection){
if(err) {
throw err;
}
// if no error apply a find() and get reference to doc
collection.find().sort({
$natural: -1
}).limit(1).nextObject(function(err, doc) {
// Rewind the cursor, resetting it to point to the start of the query
if(err) {
throw err;
}
// using tailable cursor get reference to our very first doc
var query = {
_id: {
$gt: doc._id
}
};
var options = {
tailable: true,
awaitdata: true,
numberOfRetries: -1
};
var cursor = collection.find(query, options).sort({
$natural: 1
});
// This function will take cursor to next doc from current as soon as 'notifications' database is updated
function next() {
cursor.nextObject(function(err, message) {
if (err) throw err;
console.log(message.message);
mdsok.volatile.emit('notification', message);
next();
});
}
// what you need to do is: call it first time
next();
});
This is what i am doing in my code.
what should I do to update the value in the browser when I update the same in db.
Please help me . Thanks in advance!
My problem was solved upto some extent.
var http = require('http'),
fs = require('fs'),
// NEVER use a Sync function except at start-up!
index = fs.readFileSync('index.html');
// Send index.html to all requests
var app = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.end(index);
});
// Socket.io server listens to our app
var io = require('socket.io').listen(app);
var MongoClient = require('mongodb').MongoClient;
function getdata(){
MongoClient.connect("mongodb://127.0.0.1:27017/test", function(err, db) {
var collection = db.collection('my_collection');
var stream = collection.find({
//'_id': new ObjectID('53eb6f2e75fd7ad00d000029')
//_id: ObjectID.createFromHexString("53eb6f2e75fd7ad00d000029")
}).stream();
stream.on("data", function(item) {
io.sockets.emit('db_status', {
status: item.status
});
prev = item.status;
console.log(prev);
});
stream.on("end", function() {
console.log("Done loading data");
});
});
}
// Send current time every 5 secs
setInterval(getdata, 5000);
// Emit welcome message on connection
io.sockets.on('connection', function(socket) {
socket.emit('welcome', {
message: 'Welcome!'
});
socket.on('i am client',function(data){
console.log(data);
});
});
app.listen(3000);
for every 5 secs, i am hitting the db and getting the value and displaying it in the browser.
To get the newly inserted object, we are using .nextObject() in node.js
Is there any way to get the updated object of the db as above in node.js.