socket.io fails to emit in express app.post callback - javascript

I have an express application that opens up a socket connection with my frontend React application.
I want to emit an event to the connected socket whenever someone sends a post request to my server with json data but socket.emit doesn't fire in a.post callback. io.sockets.emit however works fine but is of no use to me in this case.
This fails:
io.on('connection', (socket) => {
app.post('/event', (req, res) => {
socket.emit('someevent', req.body);
res.sendStatus(200);
}
}
But this passes:
io.on('connection', (socket) => {
app.post('/event', (req, res) => {
io.sockets.emit('someevent', req.body);
res.sendStatus(200);
}
}

SLaks's comment is correct but it did not help me solve my problem.
What I ended up doing is:
In the post request coming to /event from the client, I added a hidden input field containing the ID of socket connection.
Then in my /event route handler, I did:
app.post('/event', function(req, res) {
io.sockets.in(req.body.socketId).emit('someevent', req.body);
res.sendStatus(200);
});
This works because by default each socket connection joins a room identified with its socket-id and messages can be sent to rooms using the io object iteself (no need to obtain a socket object from io.on('connection', socket =>{})

Related

How to list all messages from mongodb to client using socket.io?

I've a database with schema named Message where it contains alot of post.
How can i list all those post whenever i loggedin into my account. I've put on socket connection as
io.on('connection', async (socket) => {
Message.find({}, (err, docs) => {
socket.emit("list message", docs) //emit list message on connection
})})
and on client (react) as
if(socket) //if socket is not null
socket.on('list message', (data) ={// do things with data})
But i cant get any day on login or even when refereshing.
where can be problem?
Thank you for your help

How to emit a socket.io response within post request in NodeJS

I have a node server running a react application, integrated with Socket.io. All works fine. I also have an external application that uses the same data. What I want to do is, when the data changes, post to my node server and then in the response, emit to any data to users who are currently subscribed to the socket.
//SERVER CODE LIVES ABOVE HERE...
const io = require('socket.io')(server);
io.on('connection', (socket) => {
socket.on('create data', function(data) {
//a place to create data, once complete triggers everyone subscribed to get an update.
socket.emit('data created', data);
});
});
app.post('/api/datacreated/', function(req, res) {
//HOW DO I EMIT IN HERE?! - this is coming from an external resource
socket.emit('data created', data);
})
Cheers for any time you've got!
Socket is locally scoped. io.sockets is not, so you can do:
app.post('/api/datacreated/', function(req, res) {
//this is coming from an external resource
io.sockets.emit('data created', data);
})

Client not updating realtime with Socket.io and Node.js

Why isn't my client side updating automatically using socket.io and node.js?
My backend accepts JSON POST requests from PHP, then it emits the data to all connected devices.
My backend code
app.post('/', function (req, res) {
console.log(req.body);
subdata = req.body;
res.send('ok');
});
io.sockets.on('connection', function (socket) {
socket.broadcast.emit('info', subdata);
});
Client side
<script>
var socket = io.connect('http://127.0.0.1:3000/');
socket.on('info', function (data) {
console.log(data);
});
</script>
That's because you only ever emit once when a new socket.io connection is made. If the app.post callback is called again, there's nothing to emit another message from socket.io.
You want to emit from within your app.post callback, and stop using global variables.

Nodejs pass server data to the socket?

I created a user login with nodejs and mongodb. I have a router. I stripped some of the code out below, but the main routes I am concerned with in this question are the /profile and /logout routes.
Basically I want to pass the req or res data to the socket when the route is made. Since the routes are on the server I am not sure how to emit the data. I mean typically you emit from client to server and the other way around, not server to server.
So maybe I am being blind or am not knowledgeable enough, but my question is how can I pass that data to my socket.
module.exports.initialize = function(app, passport) {
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profile', { user : req.user });
//socket.emit('user loggedIn', { user : req.user })
});
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
// route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
};
Side Note: My socket code sits in my server.js so example.
var users = {};
io.sockets.on('connection', function (socket) {
// Listen to a new user then emit the user to all clients
socket.on('user loggedIn', function (data) {
socket.userName = data;
users[socket.userName] = socket;
io.sockets.emit('user name', Object.keys(users));
console.log(users);
});
});
Basically I want to just store all the logged in users inside an object and emit to the client all the logged in users and allow them to have a live chat.
It appears all I need to do is pass that data to my socket, so I am sure passing that data is simple, but I DONT KNOW HOW!
Thanks!
Clint side code
but username should be unique
socket.emit('myname',{username:'uniqueid});
server side code
var onlineuser=[];
socket.on('myname',function(data){
socket.username=data.username;
onlineuser.push(data.username);
io.sockets.emit('onlineuser',onlineuser);
});
socket.on('disconnect',function()
{
var i=onlineuser.indexOf(socket.username);
onlineuser.splice(i,1);
io.sockets.emit('onlineuser',onlineuser);
});

How does nodejs usually manipulate DOM from the backend without using socket

Usually what I would do is
In backend
socket.emit("manipulate", data);
In frontend
socket.on("manipulate", data);
So that you can signal Jquery to manipulate the DOM in frontend
However because I want to manipulate the DOM in app.js where
FILES
app.js
backend.js
ui.js
app.js
app.post('/test', function(req, res){
res.sendfile(__dirname + '/views/test.html');
Backend.manipulate(req.body, function(err, data){
if (err) throw err;
// how do I manipulate DOM here
});
});
backend.js
exports.listen = function(server){
io = socketio.listen(server);
io.set('log level', 2);
io.sockets.on('connection', function(socket){
});
}
I don't have access to socket, and I can't move exports.listen as all my socket manipulation is there.
Any advice would be appreciated
Edit:
For clarification on the use case, say that I have a registration form in the front end, the registration is submit through POST, and POST calls a function in backend.js that register the user, after backend.js succesfully register the user it would like to send a message to the user, how would that message normally be display in frontend?

Categories