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

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.

Related

Broadcast an HTML page to clients in Nodejs with Express

I am developing a client-server app with Nodejs and Express. I'd like to send an HTML page (for example index.html) to all the clients connected to the server.
The server allows the user to log in with name and password, this connection data are stored with an array just like this:
app.post('/myaction', function(req, res) {
clients.push({
"name": req.body.nombre,
"direction":req.connection.remoteAddress,
"time": getDate(),
"role" : role
});
}
So the IP directions are stored in this array too. I can loop with a forEach loop:
clients.forEach(function (client) {
});
Which Express function allows me to send an HTML document to all these clients stored in the array?
You can't achieve that using express. The best approach is to use websockets to push data to all connected clients. I recommend using Socket.io for that since it's really simple to use.
const app = require('express')();
const server = require('http').Server(app);
const io = require('socket.io')(server);
io.on('connection', socket => {
console.log('User connected');
});
app.post('/myaction', (req, res) => {
io.emit('data', 'some-data');
res.send('Data sent to all connected users');
});
client side
// Add socket.io client side library
var socket = io();
socket.on('data', function(data) {
// Do something with the data sent from the server
});

How to read response in server after sending an alert to specific user in socket.io?

I'm new to Socket.io. Here is my problem.
I want to get the real time location of Android device. So I created a simple app to get current GPS location. And Node.js server and also Angular Admin panel.
Here is my Node.js server code.
//Some import statements are missing here. Not added.
var app = require('express')();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
// Creating the socket connection.
io.sockets.on('connection', function (socket) {
socket.on('join', function (data) {
socket.join(data.id);
});
});
module.exports = function (app, express) {
var api = express.Router();
api.post('/device_location/:child_id', function (req, res) {
var child_id = req.body.child_id;
io.sockets.in(child_id).emit('new_msg', {msg: 'gps_data'}); //Sending request to registered android device.
var gps_location = ""; //Here i want to take GPS data from android client.
res.json({ type: "success", code: 200, data: gps_location }); //Then i can send the response to anyone who need that.
});
return api;
};
If this is not clear, please check this gist : https://gist.github.com/chanakaDe/123080fa5427c38c37f36afdac10be7c
First I created the socket connection. Then Android client can connect to it with unique user ID.
Then I'm sending the request to get GPS data when admin press the button from the Administration button.
io.sockets.in(child_id).emit('new_msg', {msg: 'gps_data'});
Here, child_id is the ID of android application.
Then I want to get the response from Android app and read it in server.
After reading that, I can send that to anyone asking for it.
res.json({ type: "success", code: 200, data: gps_location });
This is the normal Node.js way of sending a response.
How can we get the response to this var gps_location = ""; variable which we are getting GPS value of specific user.
Please help me on this. Tried many ways, but not good. I just need to read the response from Android client in the server and process it.
You need to emit your GPS location from Android to your server using something like :
socket.emit("gpsdata", data)
and then receive it in Node using socket.on("gpsdata", doSomething) :
io.sockets.on('connection', socket => {
socket.on("gpsdata", data => { // Receive data from one socket
io.sockets.emit('gps_location', { gps_location : data }) // Emit to everyone
})
});
https://socket.io/docs/emit-cheatsheet/

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);
})

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

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 =>{})

How to send commands from client to server with Socket.io

I would like to send commands from client to server example change image url or label text. I have managed to get the connection working between server & client and the button clicks to work, but i cant manipulate the DOM from the index.js file. Is there a solid way to do this? My client side uses PHP to get data from mySQL database and i'd like to pass that data as array to server and render to view. Here is my code so far:
server: index.js -
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get("/",function(req,res){
res.sendFile(__dirname + '/index.html');
app.use(express.static(__dirname));
});
//This is auto initiated event when Client connects to Your Machien.
io.on('connection', function(client) {
console.log('Client connected...');
client.on('test',function(msg){
console.log("i can see this in cmd console");
// i would like to do like this but it says "document is not defined"
//document.getElementById("mediaContainer").innerHTML = "Paragraph changed!";
});
});
http.listen(3000,function(){
console.log("Listening on 3000");
});
client: app.js -
$(document).ready(function () {
$("#button1").click(function(){
socket.emit('test',$("#someinput").val());
});
});
I would like it to work like this rather:
server: app.js -
$(document).ready(function () {
var socket = io.connect('http://192.168.2.65:3000');
socket.on('test',function(msg){
$("#mediaContainer").append(msg);
console.log("i cant get this to work");
});
});
Thanks :)
Got it to work. Had to make a socket.emit inside the socket.on that catch it with another server javascript file like this:
index.js:
client.on('test',function(value){
io.sockets.emit('testi1',value);
});
app.js:
socket.on('testi1',function(msg){
$("#mediaContainer").append(msg + '<br /><br />');
});
There are two sides to socket.io, BackEnd and FrontEnd.
In the code above, you tried to manipulate the DOM like document.getElementById("mediaContainer").innerHTML = "Paragraph changed!";
but this is the FrontEnd part.
How socket.io works is you use js provided by socket in the FrontEnd to emit something to the server where the socket in the BackEnd will be listening to. Then, you emit something from BackEnd in response to the received emission. You also add a listener at the FrontEnd part to this BackEnd emission and finally manipulate the DOM according to the received emission.
FrontEnd
$(document).ready(function () {
var socket = io.connect('http://192.168.2.65:3000');
$("#button1").click(function(){
socket.emit('test',$("#someinput").val());
});
socket.on('test',function(msg){
$("#mediaContainer").append(msg);
});
});
BackEnd
io.on('connection', function(client) {
console.log('Client connected...');
client.on('test',function(msg){
// If you want all including the sender to get emission
client.emit('test', msg);
// If you want all excluding the sender to get emission
client.broadcast.emit('test', msg);
});
});
This should work. Cheers!!

Categories