Socket.IO always emits to last connected client - javascript

I have a problem with Socket.IO (Node.JS).
I try to emit something to a client that makes a request, but Socket.IO answers to the latest connected client.
For example: I connect with my computer to the site, and connect with my laptop after that. Now I make a request with my computer, but my laptop is getting the answer.
My code looks like this:
Server:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server, { log: false });
var socket = socket;
io.sockets.on('connection', function (socket_) {
socket = socket_;
socket.on('dl_me', function (result) {
downloadTrack(result, result.song_uri);
if (typeof callback == 'function' ) {
callback({
success: success
});
}
});
});
var downloadTrack = function(result, uri) {
socket.emit('gotodownload', {
id: generated_number
});
}
Client:
var socket = io.connect( window.location.href );
socket.on('gotodownload', function(result) {
var linktodl = window.location.host + '/getme/' + result.id;
document.getElementById('dlbutton').innerHTML = 'Download!'
});
It's not the complete code, but every relevant socket.io part.

Try passing the socket object to your downloadTrack function:
// Add an argument for the socket object.
var downloadTrack = function(socket, result, uri) {
socket.emit('gotodownload', {
id: generated_number
});
}
And modify the code inside dl_me event to call the function like:
socket.on('dl_me', function (result) {
// Pass the socket to the function.
downloadTrack(socket, result, result.song_uri);
// ...
});

Related

Making ajax call to node server

I am new to NodeJS and trying to use npm spotcrime package to get crime data from user input location on click of a button through ajax call. Here is the usage of the package given on npm documentation page of package.
var spotcrime = require('spotcrime');
// somewhere near phoenix, az
var loc = {
lat: 33.39657,
lon: -112.03422
};
var radius = 0.01; // this is miles
spotcrime.getCrimes(loc, radius, function(err, crimes){
});
which works perfectly fine when run separately and returns correct crime json data. However I don't understand how to call this through ajax call on click of button. Any insights would be really helpful. Thanks in advance :)
UPDATE
Here is my server code
var express = require('express');
var app = express();
var dataFile = require('./data/data.json');
var reload = require('reload');
var path = require('path');
app.set('port', process.env.PORT || 3000);
app.set('appData', dataFile);
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.use(express.static(path.join(__dirname, '/public')));
app.use(require('./routes/index'));
app.use(require('./routes/information'));
app.use(require('./routes/spotcrime'));
var server = app.listen(app.get('port'), function(){
console.log('Go to http://localhost:' + app.get('port')+ ' on your
browser');
});
reload(app);
And here is spotcrime.js file
var express = require('express');
var router = express.Router();
var spotcrime = require('spotcrime');
router.get('/spotcrime', function(request, response){
var loc = {
lat: 33.39657,
lon: -112.03422
};
var radius = 0.01; // this is miles
spotcrime.getCrimes(loc, radius, function(err, crimes){
response.send(crimes);
});
});
module.exports = router;
I am trying this from quite a while but nothing shows up. Please suggest any way out
use this code to make ajax call
var http = require('http');
var request = require('request');
request.post({
url: "xxxxxxxxxxxx",
method: "POST",
json: true, // <--Very important!!!
body: {}
},
function(error, response, body) {
if (!error) {
console.log(body.d);
} else {
console.log(error);
}
}
);
If I understood correctly you want to send an AJAX request from a browser(front-end) to your server. This can easily be done with jQuery AJAX see the official documentation page. Here is an example for you:
<buttom class="send-request">Send AJAX request</button>
$(".send-request").click(function() {
$.ajax({
method: "GET", // since you are waiting for GET request on server
url: "/spotcrime", // you might have to provide full path to your endpoint starting with https://127.0.0.1/spotcrime
data: { Greetings: "Hello" } // data object can be deleted since you don't expect any parameters on server side
})
.done(function( msg ) {
alert( "Response data: " + msg );
});
});

In Node.js, how to update different components of a page in different frequency?

I'm trying to build a real time webpage to show some real time statistics. This webpage has 12 components. I'm using Ajax in SetTimeout to update each component. Since I'd like to update each component in different frequency, I write a setTimeout function for each component and gives each component a link (defined in "main.js"). Looks like:
(function poll() {
setTimeout(function() {
$.ajax({
url: url1,
type: 'GET',
success : function(info){
var object = document.getElementById("1");
object.textContent = info;
}, complete: poll });
}, 5000);
})();
...
...
(function poll() {
setTimeout(function() {
$.ajax({
url: url12,
type: 'GET',
success : function(info){
var object = document.getElementById("12");
object.textContent = info;
}, complete: poll });
}, 10000);
})();
And in my "server.js", I hope to connect to database only once and then render different components. The configuration of the database will rely on the link so I organize the app like this:
app.get('/:A/:B', function(req,res){
var A= req.params.A;
var B = req.params.B;
var config = something relies on A and B
var client = new pg.Client(config);
client.connect(function(err){
if (err) {
console.log("Error occurred when try to connect the database",err);
}
else {
res.sendFile(__dirname + '/public/main.html');
app.get('/main.js', function(req,res){
res.sendFile(__dirname + '/public/main.js');
});
app.get('/url1',function(req,res) {
//query database and send the data url1 needs
});
...
...
app.get('/url12',function(req,res) {
//query database and send the data url12 needs
});
})
I want to ask if writing "app.get()" within "app.get()" like the code above is good practice. If not, how can I keep a global connection to the database and use it for different components? Also, is there any improvement I can make to this web app? I'm quite new to Node.js
If I had to do this with callbacks instead of promises, this is how I would do it on Server side.
first, I would use your endpoint to get the client, but would put it in a module internal variable, and still send a response if I failed to connect to DB.
var db=null;
app.get('/:A/:B', function(req,res){
var A= req.params.A;
var B = req.params.B;
var config = something relies on A and B
var client = new pg.Client(config);
client.connect(function(err){
if (err) {
console.log("Error occurred when try to connect the database",err);
res.status(503).send("Error connecting to database);
}
else {
db = client;
res.sendFile(__dirname + '/public/main.html');
}
}
}
Then, I would write a function that would reuse that DB if it exists:
function usingDatabase(req,res,next){
if(db) {
req.db=db;
next();
}
else {
res.status(400).send("Bad request. open the DB first by calling /:A/:B");
}
}
finally I'd use it like this:
app.get('/main.js', function(req,res){
res.sendFile(__dirname + '/public/main.js');
});
app.get('/url1',usingDatabase, function(req,res) {
// db is in req.db;
//query database and send the data url1 needs
});
...
...
app.get('/url12',usingDatabase,function(req,res) {
// db is in req.db;
//query database and send the data url12 needs
});

Meteor.method hangs on call

I have a meteor code that calls an method on the server. The server code executes an API call to the USDA and puts the resulting json set into a array list. The problem is that after the Meteor.call on the client side, it hangs.
var ndbItems = [];
if (Meteor.isClient) {
Template.body.events({
"submit .searchNDB" : function(event) {
ndbItems = [];
var ndbsearch = event.target.text.value;
Meteor.call('getNDB', ndbsearch);
console.log("This doesn't show in console.");
return false;
}
});
}
if (Meteor.isServer) {
Meteor.methods({
'getNDB' : function(searchNDB) {
this.unblock();
var ndbresult = HTTP.call("GET", "http://api.nal.usda.gov/ndb/search/",
{params: {api_key: "KEY", format: "json", q: searchNDB}});
var ndbJSON = JSON.parse(ndbresult.content);
var ndbItem = ndbJSON.list.item;
for (var i in ndbItem) {
var tempObj = {};
tempObj['ndbno'] = ndbItem[i].ndbno;
tempObj['name'] = ndbItem[i].name;
tempObj['group'] = ndbItem[i].group;
ndbItems.push(tempObj);
}
console.log(ndbItems); //This shows in console.
console.log("This also shows in console.");
}
});
}
After the call to the server and the API returns data to the console and writes it to the array, it doesn't process the console.log on the client side 1 line below the method call. How can I fix this?
You forgot to give your client side call a callback function. Method calls on the client are async, because there are no fibers on the client. Use this:
if (Meteor.isClient) {
Template.body.events({
"submit .searchNDB" : function(event) {
ndbItems = [];
var ndbsearch = event.target.text.value;
Meteor.call('getNDB', ndbsearch, function(err, result) {
console.log("This will show in console once the call comes back.");
});
return false;
}
});
}
EDIT:
You must also call return on the server:
if (Meteor.isServer) {
Meteor.methods({
'getNDB' : function(searchNDB) {
this.unblock();
var ndbresult = HTTP.call("GET", "http://api.nal.usda.gov/ndb/search/",
{params: {api_key: "KEY", format: "json", q: searchNDB}});
....
console.log("This also shows in console.");
return;
}
});
}

retrieve page source using node js

I have to do retrieve the page source of a page with nodejs, but the page that I want to retrieve isn't always the same.
I have 2 files server.js that is listening and when he receive A connections he call load.js that retrive the sourse of a non defined page, my code is this:
server.js
var net = require('net');
var loadFb = require('./load.js');
var HOST = 'localhost';
var PORT = 9051;
// Create a server instance, and chain the listen function to it
// The function passed to net.createServer() becomes the event handler for the 'connection' event
// The sock object the callback function receives UNIQUE for each connection
net.createServer(function(sock) {
// We have a connection - a socket object is assigned to the connection automatically
console.log('CONNECTED: ' + sock.remoteAddress +':'+ sock.remotePort);
// Add a 'data' event handler to this instance of socket
sock.on('data', function(data) {
console.log('User request profile of: ' + data);
// Write the data back to the socket, the client will receive it as data from the server
//here I have to call test.js
//how
sock.write(data);
});
// Add a 'close' event handler to this instance of socket
sock.on('close', function(data) {
console.log('CLOSED: ' + sock.remoteAddress +' '+ sock.remotePort);
});
}).listen(PORT, HOST);
console.log('Server listening on ' + HOST +':'+ PORT);
the other file is this:
var https = require('https');
var options = {
host: 'graph.facebook.com',
port: 443,
path: '/dario.vettore',
method: 'GET'
};
var req = https.get(options, function(res) {
var pageData = "";
res.setEncoding('utf8');
res.on('data', function (chunk) {
pageData += chunk;
//console.log(pageData);
return pageData;
});
res.on('end', function(){
//response.send(pageData)
});
});
How can I ask from the first file (server.js) to the second file to retrive for it the page source from the second file, But the page that I want to get the source can change isn't always the same..
In your second file (I'm assuming that's the one named loadFb.js), you want to export a function, instead of calling the code right away.
Node caches its modules so when you require() them, the code only gets run once.
The second file should look something like this:
var https = require('https');
module.exports = function(path, callback) {
var options = {
host: 'graph.facebook.com',
port: 443,
path: path,
method: 'GET'
};
var req = https.get(options, function(res) {
var pageData = "";
res.setEncoding('utf8');
res.on('data', function (chunk) {
pageData += chunk;
});
res.on('end', function(){
callback(pageData);
});
});
};
Then in your first file, you would access it like this:
loadJs('/dario.vettore', function(pageData) {
console.log(pageData);
});
This way you can execute the module code many times, with different paths.

Parsing JSON url with NODE.JS and keeping it up to date with SOCKET.IO

I am very new to node.js and socket.io and I am trying to figure out how to read a JSON array from an external url, then parse it and display on the main page. Then I believe I use socket.io to keep that connection open and keep the JSON object up to date when a change occurs.
This is what I have so far for node.js.
var http = require("http");
var fs = require('fs');
var options = 'http://api.trakt.tv/user/watching.json/APIKEY/USERNAME';
var server = http.createServer(function(request, response){
console.log('Connection');
http.get(options, function(res){
var data = '';
res.on('data', function (chunk){
data += chunk;
});
res.on('end',function(){
var obj = JSON.parse(data);
console.log( obj );
})
});
response.end();
});
server.listen(8888);
When I connect to localhost:8888 I see the console show up with "connection" and then the console logs the contents of the JSON object. This is as far as I have managed to get. I would appreciate and help and pointers on how to get that JSON object displayed and styled on my index page and keep it up to date
TIA
Mark
Okay, now that I understand the problem, here is my answer. It's going to be a bit advice laden, as there is no true "right way" to do what you want. All we can be assured if is that yes, you are going to want to use WebSockets (or in this case socket.io, which can emulate websockets on older browsers).
Your current pull code is probably fine, though you're going to want to tweak that code to run on a timeout so that the latest JSON is pulled every so often. In addition, we want to keep the various moving parts of this seperate: Reading from the API/writing the cache, listening to the cache, and then feeding the cache out to connected clients:
var http = require("http");
var fs = require('fs');
var url = 'http://api.trakt.tv/user/watching.json/APIKEY/USERNAME';
var cacheFile = '/path/to/cachefile';
var connectedSockets = [];
function fetchJson() {
http.get(url, function(res) {
body = '';
res.on('data', function(data) {
body += data;
});
res.on('end', function() {
fs.writeFileSync(cacheFile, body);
setTimeout(fetchJson, 1000); // Fetch it again in a second
});
})
}
fetchJson(); // Start fetching to our JSON cache
// Start watching our cache file
fs.watch(cacheFile, function(event, filename) {
if(event == 'change') {
fs.readFile(cacheFile, function(data) {
connectedSockets.forEach(function(socket) {
socket.emit('data', JSON.parse(data));
});
});
}
});
// Now setup our socket server
var io = require('socket.io').listen(8888);
io.sockets.on('connection', function(socket) {
connectedSockets.push(socket);
});
I don't handle disconnected here (you'll want to remove disconnected or err'ed sockets from the connectedSockets list), and I didn't actually run this...but it should give you an idea of where to head.
On the client, it should be a matter of simply:
var socket = io.connect('http://localhost:8888');
socket.on('data', function (data) {
// Data will contain your JSON object, do your DOM manip here
});

Categories