Socket IO -- socket.emit firing every event twice - node.js

socket.js:
var state = {
io: null
}
exports.init = function(io) {
state.io = io;
}
exports.get = function() {
return state.io;
}
exports.emit = function(message, data) {
console.log("emitting")
state.io.emit(message, data);
}
exports.onConnection = function(callback) {
state.io.once('connection', function (socket) {
callback(socket);
});
}
tags.js:
router.get('/', function (req, res) {
var DeviceIdentifier = 'WILL'
var NDefRecord = 'FROM_WILL'
req.headers['x-name'] = DeviceIdentifier
req.headers['x-content'] = NDefRecord
console.log("tags.js: GET");
socket.emit("tag:scan", {name: "000000000a0d9439", content: "adsf});
})
server.js
var io = require('socket.io')(server);
var socket = require('./socket');
socket.init(io);
socket.onConnection(function (data) {
console.log("Got Connection");
console.log(data);
});
No matter how I am doing it, the socket.emit function is called twice and data is getting stored twice as well.
I've tried looking up many examples and the problem still seems like it is persisting
Any help would be appreciated.
Thanks!

just add res.send . you are not sending any response to the browser so he try to refresh after x seconds
router.get('/', function (req, res) {
var DeviceIdentifier = 'WILL'
var NDefRecord = 'FROM_WILL'
req.headers['x-name'] = DeviceIdentifier
req.headers['x-content'] = NDefRecord
console.log("tags.js: GET");
socket.emit("tag:scan", {name: "000000000a0d9439", content: "adsf});
res.send('ok');
})

Related

Socket.io - server receives message but doesn't emit it to clients using nodejs and mongodb?

when i run the code, the server server side receive the message but the client side doesnt get anything until they send message. however in html doesnt show anything wrong
i have this server code:
var http = require('http').Server(app);
var io = require('socket.io')(http);
var cors = require('cors')
const { socket } = require('socket.io');
io.on('connection', () =>{
console.log('a user is connected')
})
i have this route:
var http = require('http').Server(router);
var io = require('socket.io')(http);
// Render Message
router.get('/messages/:id', async function (req, res, next) {
user = await User.findOne({_id: req.session.userId}, {username: 1})
return res.render("user/messages.ejs", {user: user, booking: req.params.id});
});
// Display Message from DB
router.get('/messageslist/:booking', (req, res) => {
Message.find({booking: req.params.booking})
.populate({
path: "pro",
model: Pro,
}).populate({
path: "user",
model: User,
}).exec().then((data) => {
res.json(data)
})
})
router.post('/messages', async (req, res) => {
const {booking, user, message} = req.body;
try {
var msg = new Message({
booking: booking,
message: message,
user: user
});
var savedMessage = await msg.save()
console.log('saved');
io.emit('message', req.body);
res.sendStatus(200);
} catch (error) {
res.sendStatus(500);
return console.log('error', error);
} finally {
console.log('Message Posted')
}
})
this is my html:
var socket = io();
$(() => {
$("#send").click(() => {
sendMessage({
booking: $("input[name=booking]").val(),
user: $("input[name=user]").val(),
message: $("#message").val()
});
})
getMessages()
})
socket.on('message', addMessages)
function addMessages(message) {
if (message.user && message.user != '') {
if ($("input[name=user]").val() == message.user._id) {
html = '<div class="msg right-msg"><div class="msg-img" style="background-image: url(' + message.user.image +
')"></div>'
html += '<div class="msg-bubble"><div class="msg-info"><div class="msg-info-name">' + message.user.username +
'</div><div class="msg-info-time">' + message.createdAt + '</div></div>'
}
} else {
html = '<div class="msg left-msg"><div class="msg-img" style="background-image: url(' + message.pro.image +
')"></div>'
html += '<div class="msg-bubble"><div class="msg-info"><div class="msg-info-name">' + message.pro.username +
'</div><div class="msg-info-time">' + message.createdAt + '</div></div>'
}
html += '<div class="msg-text">' + message.message + '</div></div></div>'
window.scrollTo(0, document.body.scrollHeight);
$("#msger-chat")+$(".msger-chat").append(html)
}
function getMessages() {
$.get('http://127.0.0.1:3000/messageslist/<%=booking%>', (data) => {
data.forEach(addMessages);
})
}
function sendMessage(message) {
$.post('http://127.0.0.1:3000/messages', message)
}
When i run it, my server outputs: User connected and message saved;. But my client doesn't get a response
I think the problem is you are creating two io instances. One in server code
var http = require('http').Server(app);
var io = require('socket.io')(http);
var cors = require('cors')
const { socket } = require('socket.io');
io.on('connection', () =>{
console.log('a user is connected')
})
another one is in route handlers
var http = require('http').Server(router);
var io = require('socket.io')(http);
You should have a singleton io object which is responsible to handle all the activities. This is an approach how to create such design. you will have mainSocketServer
createSocketServer = (server) => {
// this is how you implemented
var io = require('socket.io')(http);
// this is the part to create singleton object
serverStore.setSocketServerInstance(io);
io.on("connection", (socket) => {
// this socket obj will include
about connected user. this socket is actually connected user client
console.log('a user is connected')
socket.on("direct-message", (data) => {
// you create socket events handler in different file
directMessageHandler(socket, data);
}); });};
module.exports = {
createSocketServer,
};
you need another file where you store all the connected users. usually in socket server, users are stored in a Map
const connectedUsers = new Map();
let activeRooms = [];
let io = null;
// we call this in mainSocketServer file
const setSocketServerInstance = (ioInstance) => {
io = ioInstance;
};
// you export this and use it anywhere on your server
const getSocketServerInstance = () => {
return io;
};
On the client side where you listen for sockets, you do not pass reference to the function. 2nd argument is callback function that has received data as parameter and you should call addMessage from inside. Here is the example code:
socket.on('message', (data) => {
addMessages(data)
})
Just update this in front end code and it should work

Heroku Nodejs Webhosting

Im trying to host a election website.
My Current Method explained:
There is server.js file with serves the public file. If its a POST request(sent by frontend.js to send data to server) edits the poll.json file based on the data sent.
I have a public file having index.html, frontend.js, poll.json where poll.json stores all the data.
My current code work all well in my localhost.
But when running it in Heroku I get a error in the POST request line saying 'POST http://localhost:53390/ net::ERR_CONNECTION_REFUSED1
*********.herokuapp.com/:1 Uncaught (in promise) TypeError: Failed to fetch'
My server.js code:
const createServer = require('http').createServer;
const express = require('express');
const app = express();
let pollData = require(__dirname+'/public/poll.json');
const fs = require('fs');
var all_usn_no=[];
const listening_port=process.env.PORT || 4000;
function get_roll_and_usn(pollData){
for(var i=0;i<=pollData.students.length-1;i++){
//all_roll_no.push(pollData.students[i][0]);
all_usn_no.push(pollData.students[i][1]);
}
}
function roll_to_row(in_usn){
get_roll_and_usn(pollData)
return all_usn_no.indexOf(in_usn);
}
function write_vote(votes){
var checking_row=roll_to_row(votes[1]);
pollData.students[checking_row]=votes;
fs.writeFile(__dirname+'/public/poll.json', JSON.stringify(pollData), (err) => {
if (err) throw err;
console.log('Data written to file');
});
}
write_vote([listening_port,0]);
app.use(express.static(__dirname+'/public'));
app.get('/', (req, res) => {
res.sendFile(__dirname);// + '/index.html');
});
app.post('/', (req, res) => {
let body = '';
req.on('data', data => body += data)
req.on('end', () => {
res.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET',
});
body=body.split(",");
console.log(body.toString());
write_vote(body);
res.end(`{ "response": "${body ? body : 'No body sent' }" }`);
})
});
app.listen(listening_port, () => {
console.log('Example app listening at http://localhost:'+listening_port)
});
my frontend.js program:
var roll='';
var client_ip='';
var usn='';
var date='';
const all_roll_no=[]
const all_usn_no=[]
var port='';
function check(roll,usn){
var data='';
const url='poll.json';
const Http = new XMLHttpRequest();
Http.open("GET", url);
Http.send();
Http.onload = () =>{
data=JSON.parse(Http.response);
get_roll_and_usn(data);
check_validity(roll,usn,data);
}
}
function get_roll_and_usn(pollData){
for(var i=0;i<=pollData.students.length-1;i++){
//all_roll_no.push(pollData.students[i][0]);
all_usn_no.push(pollData.students[i][1]);
}
}
function usn_to_row(in_usn){
return all_usn_no.indexOf(in_usn);
}
function check_validity(checking_roll,checking_usn,data){
var checking_row=usn_to_row(checking_usn);
port=data.students[0][0];
//if(all_roll_no.indexOf(checking_roll)>=0 && checking_usn==all_usn_no[all_roll_no.indexOf(checking_roll)] && data.students[checking_row][2]==0){
if(all_usn_no.indexOf(checking_usn)>=0 && data.students[checking_row][2]==0){
//console.log("valid");
document.getElementById("page_2").style.display = "none";
document.getElementById("page_3").style.display = "block";
fetch('https://api.ipify.org/?format=json').then(results=> results.json()).then(data => client_ip=data.ip);
}
else{
alert("You cannot vote/ You have already voted")
//console.log('invalid');
}
}
document.getElementById("startbutton").onclick = function(){
roll = document.getElementById("roll_no").value;
usn = document.getElementById("usn_no").value;
date = Date();
check(roll,usn);
}
document.getElementById("next").onclick = function() {
document.getElementById("page_1").style.display = "none";
document.getElementById("page_2").style.display = "block";
}
document.getElementById("finish").onclick = function() {
var splb=[document.getElementById("splb1").checked,document.getElementById("splb2").checked,document.getElementById("splb3").checked,document.getElementById("splb4").checked,document.getElementById("splb5").checked,document.getElementById("splb6").checked,document.getElementById("splb7").checked];
var splg=[document.getElementById("splg1").checked,document.getElementById("splg2").checked,document.getElementById("splg3").checked,document.getElementById("splg4").checked,document.getElementById("splg5").checked,document.getElementById("splg6").checked,document.getElementById("splg7").checked];
var asplb=[document.getElementById("asplb1").checked,document.getElementById("asplb2").checked,document.getElementById("asplb3").checked,document.getElementById("asplb4").checked,document.getElementById("asplb5").checked,document.getElementById("asplb6").checked,document.getElementById("asplb7").checked];
var asplg=[document.getElementById("asplg1").checked,document.getElementById("asplg2").checked,document.getElementById("asplg3").checked,document.getElementById("asplg4").checked,document.getElementById("asplg5").checked,document.getElementById("asplg6").checked,document.getElementById("asplg7").checked];
var csb=[document.getElementById("csb1").checked,document.getElementById("csb2").checked,document.getElementById("csb3").checked,document.getElementById("csb4").checked,document.getElementById("csb5").checked,document.getElementById("csb6").checked,document.getElementById("csb7").checked];
var csg=[document.getElementById("csg1").checked,document.getElementById("csg2").checked,document.getElementById("csg3").checked,document.getElementById("csg4").checked,document.getElementById("csg5").checked,document.getElementById("csg6").checked,document.getElementById("csg7").checked];
var acsb=[document.getElementById("acsb1").checked,document.getElementById("acsb2").checked,document.getElementById("acsb3").checked,document.getElementById("acsb4").checked,document.getElementById("acsb5").checked,document.getElementById("acsb6").checked,document.getElementById("acsb7").checked];
var acsg=[document.getElementById("acsg1").checked,document.getElementById("acsg2").checked,document.getElementById("acsg3").checked,document.getElementById("acsg4").checked,document.getElementById("acsg5").checked,document.getElementById("acsg6").checked,document.getElementById("acsg7").checked];
var scb=[document.getElementById("scb1").checked,document.getElementById("scb2").checked,document.getElementById("scb3").checked,document.getElementById("scb4").checked,document.getElementById("scb5").checked,document.getElementById("scb6").checked,document.getElementById("scb7").checked];
var scg=[document.getElementById("scg1").checked,document.getElementById("scg2").checked,document.getElementById("scg3").checked,document.getElementById("scg4").checked,document.getElementById("scg5").checked,document.getElementById("scg6").checked,document.getElementById("scg7").checked];
var ascb=[document.getElementById("ascb1").checked,document.getElementById("ascb2").checked,document.getElementById("ascb3").checked,document.getElementById("ascb4").checked,document.getElementById("ascb5").checked,document.getElementById("ascb6").checked,document.getElementById("ascb7").checked];
var ascg=[document.getElementById("ascg1").checked,document.getElementById("ascg2").checked,document.getElementById("ascg3").checked,document.getElementById("ascg4").checked,document.getElementById("ascg5").checked,document.getElementById("ascg6").checked,document.getElementById("ascg7").checked];
var vote=[String(splb.indexOf(true)),String(splg.indexOf(true)),String(asplb.indexOf(true)),String(asplg.indexOf(true)),String(csb.indexOf(true)),String(csg.indexOf(true)),String(acsb.indexOf(true)),String(acsg.indexOf(true)),String(scb.indexOf(true)),String(scg.indexOf(true)),String(ascb.indexOf(true)),String(ascg.indexOf(true))]
var update=[String(roll),String(usn),"1",String(client_ip),String(date)].concat(vote);
if (update.indexOf("-1")<0){
alert("Pls vote for all posts")
}
else{
document.getElementById("page_1").style.display = "none";
document.getElementById("page_2").style.display = "none";
document.getElementById("page_3").style.display = "none";
fetch('http://localhost:'+port,{method:'POST',body:update}).then(results=> results.json()).then(console.log);
//console.log(update);
alert("Your vote has been registered")
}
}
You can just ignore the function as they are just to process the data and do necessary funtions.
Main problem: PORT request from frontend.js to server.js sending data to edit the poll.json file return error.
Thanks in advance.
Try using const PORT = process.env.PORT || 3333;
with
app.listen(PORT, () => {
console.log(`Server is starting on ${PORT}`);
})

Nodejs return result from function is empty promise

I am trying to use Nodejs tron library to create pair of wallet address and here is my code:
app.js
var app = require('express')()
var http = require('http').createServer(app)
var wallet_engine = require('./function')
app.get('/', function (req, res) {
result = wallet_engine.create_wallet_trx()
console.log(result)
res.send(result)
})
//////server listen
http.listen(8443, function () {
console.log('listening on *:8443')
})
and here is my function.js
module.exports = {
create_wallet_trx: function () {
////////generate TRX Address
var { HdTronPayments } = require('#faast/tron-payments')
var keys = HdTronPayments.generateNewKeys()
var tronPayments = new HdTronPayments({ hdKey: keys.xprv })
var address = tronPayments.getPayport(356)
var privateKey = tronPayments.getPrivateKey(356)
var trx_wallet = { privateKey: privateKey, address: address }
console.log(trx_wallet)
return trx_wallet
},
}
The problem is when i check console.log(trx_wallet) the result is there and i can see generated public and private key, also after returning data, console.log(result) is displaying data, but res.send(result) shows me empty json.
this is console.log() results
{
privateKey: Promise {
'B88BB56DAB80DB681765A0C07197DD23BB8E2FAD195BF9D0ECD09F5F8FC54297'
},
address: Promise { { address: 'TYCJSKERHReUXacw9wLorZYLDoijevvsVK' } }
}
and this is the result on my browser:
{"privateKey":{},"address":{}}
i know this is because of Nodejs Async system and i should wait to promise gets the value but i don't know how to wait for promise to get complete and then prints the result on my browser screen.
You are doing good but here many calls are asynchronous that's for you facing problem.
you should use async await or then as i did bellow it may help you..
// app js
var app = require('express')()
var http = require('http').createServer(app)
var wallet_engine = require('./function')
app.get('/', function (req, res) {
result = wallet_engine.create_wallet_trx().then(data=>{
res.json(data);
}).catch(err=>{
console.log(err);
})
})
//////server listen
http.listen(8443, function () {
console.log('listening on *:8443')
})
// function.js
var { HdTronPayments } = require('#faast/tron-payments')
module.exports = {
create_wallet_trx: async function () {
var keys = await HdTronPayments.generateNewKeys()
var tronPayments = await new HdTronPayments({ hdKey: keys.xprv })
var address = await tronPayments.getPayport(356)
var privateKey = await tronPayments.getPrivateKey(356)
var trx_wallet = { privateKey: privateKey, address: address }
return trx_wallet
}
}
result: {"privateKey":"92ACAECFE00E9F90E330A6B031F10365F29AFDD503922CC99CA8704F1BA53432","address":{"address":"TGfsHx4VU6B36AwUy8Bqt6edoNnUHpMtSQ"}}

Why promise.resolve wait forever in this case?

I am a nodejs's newbie. I'm testing a promise and have an issue.
Here's my issue.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.get('/', async function(req,res){
console.log(222);
res.send("Hello!!!");
let check;
try {
console.log(3333);
check = await test();
console.log(4444);
} catch (err) {
console.log("Error : ", err);
}
console.log(111, check);
});
function test () {
return new Promise (resolve => {
console.log(5555);
app.get('/test', function(req, res) {
count = count + 1;
res.send(count.toString());
resolve("hahahaha");
})
})
}
app.listen(9000, function(){
console.log("hehehehe");
});
In a get 'http://localhost:9000' callback, I wait for 'http://localhost:9000/test' result to do something. The thing is, it's working fine for the first time. But since the 2nd, the promise.resolve() function doesn't work.
Here is my first time log:
hehehehe
222
3333
5555
4444
111 'hahahaha'
And here is my second time log :
222
3333
5555
the promise.resovle() doesn't work. It's waiting forever and I don't understand.
EDIT : Here is the solution for using EventEmitter to do signup and smsVerifyCode after modified by the help of Mr. #Aritra Chakraborty
var express = require('express');
var userControler = require('../Controler/user');
var router = express.Router();
var utils = require('../Helper/Utils');
var user_model = require('../Models/user');
const TIMEOUT_VERIFY = 300000;
const CODE_EXPIRED = 0;
const CODE_VALID = 1;
const CODE_INVALID = 2;
const CONTACT_EXISTED = 3;
const DATABASE_ABUSED = 4;
const events = require('events');
const emitter = new events.EventEmitter();
function timeout_verify_sms_emitter (time) {
setTimeout(() => {
emitter.emit('timeout_sms');
}, time);
}
function verify_code(codeGen) {
return new Promise((resolve, reject)=>{
emitter.on("verifySMS", (data)=>{
if (data === codeGen) {
resolve(CODE_VALID);
}
else {
resolve(CODE_INVALID);
}
})
emitter.on('timeout_sms', () =>{
resolve(CODE_EXPIRED);
});
})
}
router.get('/',function(req,res){
res.send("Welcome to the Earth!!!");
})
router.post('/signup', async function(req,res){
let verifyCode;
let checkContact;
let codeGen = utils.generateCode();
try {
checkContact = await user_model.checkContact(userData.contact);
if (checkContact === true) {
res.send(CONTACT_EXISTED);
}
else {
//call send sms to contact function here
//exam : sendSMS(contact)
//
timeout_verify_sms_emitter(TIMEOUT_VERIFY);
verifyCode = await verify_code(codeGen);
}
}
catch (err) {
console.log("Error : ", err);
}
if (verifyCode === CODE_EXPIRED) {
res.send(CODE_EXPIRED);
}
else if (verifyCode === CODE_VALID) {
var result = userControler.processUserData(req.body);
if (result) {
res.send(CODE_VALID);
}
else {
res.send(DATABASE_ABUSED);
}
}
else {
res.send (CODE_INVALID);
}
})
router.post('/signup/verifySMS', function(req, res){
emitter.emit("verifySMS", req.body.smsCode);
})
module.exports = router;
According to the above code:
Whenever you do a get request to / you are CREATING a /test path.
So, the first time it works because /test path has one handler.
Second or more time it doesn't works because,
The /test route has multiple handler now.
How express works is, routes get executed according to their declaration time. (Think middlewares)
Now, Second time the /test will have 2 handlers. And when you hit /test the first handler runs. And as this is not a middlware it doesn't go to the next handler. Now, the first handler has a different resolve function then the second one. So the second resolve function doesn't run at all.(Think closure)
For what are you trying to do most web implementations use long polling. Because if you wait too long for the second route it will throw a timeout error. Means you periodically hit an api to get the status of something. Means you create 3 routes.
A main route, like /signup
A second route like /sendsms
A third route where you send a particual identifier and it returns some positve/negative value. like /sendsms/check, where you might pass the phone number.
Otherwise if you don't care about timeouts you can use EventEmitter inside the /test route.
EDIT1:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
const events = require('events');
const emitter = new events.EventEmitter();
let count = 0;
app.get('/', async function (req, res) {
console.log(222);
res.send("Hello!!!");
let check;
try {
console.log(3333);
check = await test();
console.log(4444);
}
catch (err) {
console.log("Error : ", err);
}
console.log(111, check);
});
app.get('/test', function (req, res) {
count = count + 1;
emitter.emit("test",count.toString());
res.send(count.toString());
})
function test(){
return new Promise((res)=>{
emitter.on("test", (data)=>{
res(data);
})
})
}
app.listen(9000, function () {
console.log("hehehehe");
});
EDIT2:
Regarding the solution, you need to handle the timeout differently. Let's say your timeout is 3sec. And the SMS route took 100sec to get a response or maybe it didn't even got a response. Then your function will be stuck there.
function test(sendSMSTime) {
return new Promise((res, rej) => {
emitter.on("test", (data) => {
.
.
res(data);
})
emitter.on('timeout', rej);//On timeout it will run.
})
}
function timeoutEmitter(timeout) {
setTimeout(() => {
emitter.emit('timeout');
}, timeout)
}
app.post('/signup', async function (req, res) {
try {
timeoutEmitter(3000);
.
.
}catch{
}
});

handling session variables inside http.request in express

Hi. When i print the req.session.mySessValue in UI , the value is empty. I think the assigning of req.session.mySessValue = dt.myValue; (express-session) is not proper. could anyone help me on this. Thanks in advance.my express code is
router.get('/', function(req, res, next) {
if(!req.xx) {
return res.redirect('/firstView');
}
var options = {
.......
};
var call = http.request(options, function(resp) {
resp.on('data', function(dt) {
var jsondata = JSON.parse(dt);
req.session.mySessValue = dt.myValue;
});
});
call.end();
call.on('error', function(e) {
console.log("error" +e.message)
});
var v = {
title: 'sample',
req : req
}
res.render('myview', v);
});

Resources