Insert data in mongodb using Socket.io - node.js

i am developing simple chat application and i want to store messages in mongoDb.
but i am getting error when i run this code.
can not read property '_id 'of undefined. i already create one collection call chat.
var MongoClient= require('mongodb').MongoClient;
var assert=require('assert');
var ObjectId= require('mongodb').ObjectId;
var bodyParser= require('body-parser');
var express = require('express'),
app=express();
server=require('http').createServer(app),
io= require('socket.io').listen(server),
app.use(bodyParser.urlencoded({extended:false}));
var mongo=require('mongodb');
users = {};
url='mongodb://localhost:27017/anant';
server.listen(9000, function(){
var host= server.address().address;
var port=server.address().port;
console.log("save app listen on http://%s:%s", host , port);
});
/*var server = app.listen(9000, function(){
var host= server.address().address;
var port=server.address().port;
console.log("save app listen on http://%s:%s", host , port);
});*/
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.sockets.on('connection', function(socket){
socket.on('new user', function(data , callback){
if(data in users){
callback(false);
}else{
callback(true);
socket.nickname= data;
users[socket.nickname]= socket;
updatenicknames();
}
});
io.sockets.on('send request', function(data , callback){
var name=data;
console.log(data);
});
socket.on('send message', function(data , callback){
var msg=data.trim();
if(msg.substr(0,3) === '/w '){
msg = msg.substr(3);
var ind = msg.indexOf(' ');
console.log(ind);
console.log("got it after ind ");
if(ind !== -1)
{
var name=msg.substr(0, ind);
var msg=msg.substring(ind + 1);
console.log(name);
console.log(msg);
if(name in users){
console.log("got it in if name condition");
users[name].emit('wishper', {msg: msg , nick: socket.nickname} );
console.log('whisper..! ');
} else
{
callback("enter a vlid user");
}
} else{
callback('please enter message for your wishper');
}
}else {
insertData(data);
io.sockets.emit('new message', {msg: msg , nick: socket.nickname} );
}
});
function updatenicknames(){
io.sockets.emit('usernames', Object.keys(users));
}
function insertData(data)
{
MongoClient.connect(url, function(err, db){
console.log(data);
db.collection('chat').save(data.msg , (err,result)=>{
if(err){
console.log("not inserted");
}else {
console.log("inserted");
}
});
});
}
socket.on('disconnect', function(data){
if(!socket.nickname) return;
delete users[socket.nickname];
updatenicknames();
});
});

It's because you are passing a string data, to your insertData function (judging by your code, I guess you are supposing that data is actually an object).
Then you are giving data.msg, which is obviously undefined, as the first argument of the save methods, which is expecting you to provide a valid object here.
Please also note that you are using the save method on a newly created document, instead of using insertOne.
As you can see in the api documentation, using save is now deprecated. (I guess you are using the last version which is currently 2.1)

Related

node server not working with express-ws

I have a node WebServer capable of communicating with Browser(say browserInstance) and linux terminal(say ProxyInstance) via Websockets. The job of the webserver is to handover the data from terminal to WebBrowser and vice-verse. Please find the server.js code below:
var express = require('express');
var expressWs = require('express-ws');
var expressWs = expressWs(express());
var app = expressWs.app;
var appForpage = express();
var browserInstance;
var ProxyInstance;
var browserCounter = 0;
var ProxyCounter = 0;
app.ws('/fromBrowser', function(ws, req, next) {
console.log("~~~~~~~~~~~~BROWSER");
if(browserCounter == 1){
ws.on('message', function(msg) {
console.log("Messagae from Browser :", msg);
ProxyInstance.send(msg);
});
}else{
browserInstance = ws;
ws.on('message', function(msg) {
console.log("Message from Browser :", msg);
ProxyInstance.send(msg);
});
browserCounter = 1;
}
ws.on('close', function(){
console.log("Ws Connection closed");
});
//next();
});
app.ws('/fromProxy', function(ws, req, next) {
console.log("~~~~~~~~~~~~PROXY");
if(ProxyCounter == 0){
ProxyInstance = ws;
ProxyCounter = 1;
}else if(browserCounter == 1){
ws.on('message', function(msg) {
console.log("Message from Proxy: ", msg);
browserInstance.send(msg);
});
}
ws.on('close', function(){
console.log("Ws Connection closed");
});
//next();
});
appForpage.use(express.static(__dirname + '/public/')); // index.html resides in public directory
appForpage.listen(5000)
app.listen(3000)
First I am creating ws connection from proxy to webserver(/fromProxy) and then from browser(/fromBrowser). The connection was successfully created. When i try to send data from Browser to proxy via Webserver, it works fine. In return to the 1st message at proxy end when tries to communicate Browser via WebServer, this one failed. I haven't received any message from Proxy. I need to run the respective ends in the same order(Proxy first and then Browser..).
I am just beginner to node. I haven't find any example over internet for my case. What am I missing here ?
That's really silly :( .I haven't registered my messsage callback from proxy. Please find the working code below.
var express = require('express');
var expressWs = require('express-ws');
var expressWs = expressWs(express());
var app = expressWs.app;
var appForpage = express();
var browserInstance;
var ProxyInstance;
var browserCounter = 0;
var ProxyCounter = 0;
app.ws('/fromBrowser', function(ws, req, next) {
console.log("~~~~~~~~~~~~BROWSER");
if(browserCounter == 1){
ws.on('message', function(msg) {
console.log("Messagae from Browser :", msg);
ProxyInstance.send(msg);
});
}else{
browserInstance = ws;
ws.on('message', function(msg) {
console.log("Message from Browser :", msg);
ProxyInstance.send(msg);
});
browserCounter = 1;
}
ws.on('close', function(){
console.log("Ws Connection closed");
});
//next();
});
app.ws('/fromProxy', function(ws, req, next) {
console.log("~~~~~~~~~~~~PROXY");
if(ProxyCounter == 0){
ProxyInstance = ws;
ProxyCounter = 1;
}
/*This is the place where i went wrong. damnn..*/
ws.on('message', function(msg) {
console.log("Message from Proxy: ", msg);
browserInstance.send(msg);
});
ws.on('close', function(){
console.log("Ws Connection closed");
});
//next();
});
appForpage.use(express.static(__dirname + '/public/')); // index.html resides in public directory
appForpage.listen(5000)
app.listen(3000)

Close websocket without closing express app

I have an express backend which includes:
var express = require("express");
var app = express();
var expressWs = require('express-ws')(app);
and:
app.get(/test/, function(req, res){
res.send('{"hello" : "world" }');
});
app.ws('/', function(ws, req) {
ws.on('message', function(msg){
var data = JSON.parse(msg);
if(data.action == "login"){
console.log("logged in!")
}
});
});
I want to be able to close the websocket without closing the app. How do I do this?
ws.close() is what you are looking for
Here it is :
app.get(/test/, function(req, res) {
res.send('{"hello" : "world" }');
});
app.ws('/', function(ws, req) {
ws.on('message', function(msg) {
var data = JSON.parse(msg);
if(data.action == "login"){
console.log("logged in!")
}
});
ws.on('close', function(msg) {
console.log('connection closed...');
});
});

Issue with socket.io join room

I have a issue with socket.io with rooms.
See the server code:
This code below is working properly.
io.on('connection', function(socket){
socket.join("myroom");
socket.on('chat message', function(data){
io.in("myroom").emit('chat message', data);
});
});
But I want the user to enter the room after an event.
Like the code below.
io.on('connection', function(socket){
socket.on('chat message', function(data){
io.in("myroom").emit('chat message', data);
});
socket.on('join', function(name, device, room){
socket.join("myroom");
});
});
It's almost the same code , but does not work. What am I doing wrong?
The event is being called correctly.
Edit. Added the front-end code:
var socket = io.connect('http://localhost:5000');
$('#msg_form').submit(function(){
socket.emit('chat message', $("#m").val(), "myroom");
$('#m').val('');
return false;
});
$("#user").submit(function() {
var name = $("#name").val();
var room = $("#room").val();
var device = navigator.userAgent;
if (name === "" || name.length < 2) {
$("#errors").empty();
$("#errors").append("Please enter a name");
$("#errors").show();
} else {
socket.emit("join", name, device, room);
$("#messages").focus();
}
});
Thank you.
I made this small demo to explain, I simulate the client-side event by setTimeout functions:
Server side:
var http = require('http');
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(9999);
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
socket.on('message', function(data){
io.in("myroom").emit('message', data);
});
socket.on('join', function(name, device, room){
console.log("new client has joining a room");
socket.join("myroom");
});
});
Client Side:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:9999');
setTimeout(function () { console.log("msg emmited to server");
socket.emit('join');
},
10000);
setTimeout(function () {
console.log("msg emmited to server");
socket.emit("message","message from client");
},
20000);
socket.on("message",function(data){
console.log("message received from server ="+data);
}
);
</script>
In your $("#user").submit(...) handler, you do not prevent the default action of the form so it is likely that the page is reloaded right after you hit the submit button. And, this will reset your connection right after you hit join, giving you a newly initialize connection that is not joined into the room.
You can either add return false; to that handler or add the e argument to the handler and call e.preventDefault() to prevent the page from reloading when you hit submit.
$("#user").submit(function(e) {
e.preventDefault();
var name = $("#name").val();
var room = $("#room").val();
var device = navigator.userAgent;
if (name === "" || name.length < 2) {
$("#errors").empty();
$("#errors").append("Please enter a name");
$("#errors").show();
} else {
socket.emit("join", name);
$("#messages").focus();
}
});

connect and quit message on main channel

I want to send message to users if some new person is joining or user is quiting the chat.
i don't really know where to start to get this function work.
On disconnect message 'This users is gone' to all On Connect "user is connected to the chatbox"
app.js
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
nicknames = [];
server.listen(8000);
app.get('/', function(req, res){
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function(socket){
socket.on('new user', function(data, callback){
if (nicknames.indexOf(data) != -1){
callback(false);
} else{
callback(true);
socket.nickname = data;
nicknames.push(socket.nickname);
updateNicknames();
}
});
function updateNicknames(){
io.sockets.emit('usernames', nicknames);
}
socket.on('send message', function(data){
io.sockets.emit('new message', {msg: data, nick: socket.nickname});
});
socket.on('disconnect', function(data){
if(!socket.nickname) return;
nicknames.splice(nicknames.indexOf(socket.nickname), 1);
updateNicknames();
});
})
;
You can use the broadcast function. This will broadcast to every other socket except the one that send the broadcast.
socket.on('disconnect', function () {
socket.broadcast.emit('leave',{name:name});
});
socket.on('leave', function (msg) {
//Add msg that msg.name is leaving
});

How to use socket.io in express routes?

I'm using Express with Socket.io but I can't figure out how to use SocKet.io in Express routes.
I end up doing this in "app.js"
...
...
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
var server = http.createServer(app);
var io = require("socket.io").listen(server);
app.get('/', routes.index);
app.get('/users', user.list);
app.post('/cmp', function(request, response) {
var client = new pg.Client("pg://user:pass#127.0.0.1/db_name");
client.connect(function(err) {
// Get the product_id and bid
var product_id = request.body.product_id;
var bid = request.body.bid.split('b')[1];
// If not get the connection
if(err) {
return console.error('could not connect to postgres', err);
}
client.query('select 1 from product_bid where product_id = $1 and number_bid = $2', [product_id, bid], function(err, result) {
if(err) {
return console.error('error running query', err);
}
if (result.rowCount == 1) {
// do not insert
} else {
// insert
// Insert to the DB
client.query('insert into product_bid (product_id, number_bid) values ($1, $2)', [product_id, bid], function(err, result) {
if(err) {
return console.error('error running query', err);
}
io.sockets.emit("bidSuccess", {product_id: product_id, bid: bid});
response.json(200, {message: "Message received!"});
client.end();
});
}
});
});
});
server.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
// ---------------
io.on('connection', function(socket){
console.log("alguem se ligou!");
socket.emit('event_from_server', {message: 'conectou-se ao servidor'});
});
How can I define the route to "/cmp" like this and passing the var "io" inside?
app.post('/cmp', routes.cmp);
So that in "/routes/cmp.js" I can do something like this:
exports.cmp = function(req, res){
var product_id = req.body.product_id;
var bid = req.body.bid.split('b')[1];
io.sockets.emit("bidSuccess", {product_id: product_id, bid: bid});
response.json(200, {message: "Message received!"});
};
Some clues?
How about a higher order function?
exports.cmp = function(io) {
return function(req, res){
var product_id = req.body.product_id;
var bid = req.body.bid.split('b')[1];
io.sockets.emit("bidSuccess", {product_id: product_id, bid: bid});
response.json(200, {message: "Message received!"});
}
};
and then
app.post('/cmp', routes.cmp(io));
As another option, I'll sometimes format my routes in the following format:
var routes = require('./routes/routes');
routes(app, io);
And then define routes as
module.exports = function(app, io) {
app.post('/cmp', function(req, res){
var product_id = req.body.product_id;
var bid = req.body.bid.split('b')[1];
io.sockets.emit("bidSuccess", {product_id: product_id, bid: bid});
response.json(200, {message: "Message received!"});
})
};
You can use simple middleware before routes, and then use in res object
app.use((req, res, next) => {
res.io = io
next()
})

Resources