Delay is socket.io event? - javascript

I created an ajax call to the IMBd database
// API Key
key = "4dba72b2-7558-4c0f-bd18-9ffcb0999c4e";
// Url
mainUrl = "http://api.myapifilms.com/imdb/top?token="+ key +"&format=json&data=0&start=1&end=250";
// API Call
var request = require('request');
request(mainUrl, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Storing data in an object
var obj = JSON.parse(body), //JSON Parser
movieArray = obj.data.movies, //Creating Array
item = movieArray[randomMovieRank]; //Setting random movie variable
itermArray = [item.ranking,item.title,item.year];
console.log(itermArray);
io.sockets.emit("serverAnswer", {ranking: itermArray[0], title: itermArray[1], year: itermArray});
}
});
return false;
Followed up by:
socket.on("serverAnswer", function(data){
console.log(data.title);
});
The socket.on is called on the client side. The problem I am having is that it is pulling through the data very slowly if at all. The API is working as it is console logging correctly in terminal. But client side it sometimes pulls through ad sometimes doesnt. Is there something I am doing wrong?
EDIT:
Added pastebin: http://pastebin.com/TYHsqBmK

When you invoke the emit method, your client is not guaranteed connected,you can trigger the ajax event after the client connected or emit specified messages,such as
the server:
io.on('connection',function(socket){
if(movies !== null)
{
socket.emit("serverAnswer", {movies:movies});
}
else{
//1.ajax request IMDB resource
//2.set movies variables
//3.emit message
}
});
the client:
socket.on("serverAnswer", function(data){
console.log(data);
});

Related

SignalR javascript client not picking up event from hub

I have a method on the hub however I am not getting any messages from this. I get the connection ID's from my user to connectionid mapping dictionary and loop through these connectionid's and then invoke a method on the client side called deviceDiscovered I can also confirm that the browser does connect to the hub
Here is my hub method
public async Task DetectDevice(dynamic message)
{
//We will be searching via the userid
var connectionId = Context.ConnectionId;
//now we get the connectionID from the table.
var connectionObj = ConnectionTable[connectionId];
//we now check whether this is a pathfinder or browser client
if (connectionObj.clientType == "pathfinder")
{
/*The pathfinder initiated the request and so this means the message should be forwarded to the browser client
that requested this resource*/
//Grab the data out of the dictionary.
PathfinderDetection deviceDiscoveredNotification = JsonConvert.DeserializeObject<PathfinderDetection>(message);
var userId = deviceDiscoveredNotification.userId;
var sysInfo = deviceDiscoveredNotification.sysInfo;
var found = deviceDiscoveredNotification.data;
if (found == "FOUND")
{
var deviceId = deviceDiscoveredNotification.deviceID;
var connections = ConnectionTable.Where(val => val.Value.id == connectionObj.id).Select(key => key.Key).ToList();
foreach (string connection in connections)
{
Clients.Client(connection).deviceDiscovered(deviceId);
}
}
else
{
//call a method on client side.
Clients.Group(userId.ToString()).noDevice("NOTFOUND");
}
I can see that the deviceID variable is populated and that the connection exists, however not getting anything back from the hub when looking at the client
here is my client side code:
<script>
$(document).ready(function(){
var connection = $.hubConnection("http://localhost:59016");
var contosoChatHubProxy = connection.createHubProxy('metrics');
contosoChatHubProxy.on('taskAdded', function(data){
console.log(data);
});
contosoChatHubProxy.on('deviceDiscovered', function(data) {
console.log(data);
});
contosoChatHubProxy.on('taskUpdate', function(data){
console.log(data);
});
contosoChatHubProxy.on('noDevice', function(found) {
console.log(found);
});
});
</script>

Firebase Database updates slowly sometimes not at all

Good morning everyone, I have a question regarding the behavior of my firebase database.
I am populating an end point on my database user with multiple POST requests to my express server app.js from my client like so:
element.on("click", function(){
send request 1 - endpoint1
send request 2 - endpoint2
send request 3 - endpoint3
}
Then in my app.js I have handlers at the routes that use the Request package to make three seperate GET request to the Halo Waypoint API like so:
app.post(endpoint1, function(req,res){
request(HaloAPI + endpoint1, function(error, res, body){
[store data from the response body into an
object to be sent to firebase endpoint 'user']
// User's stats
database + "/user".set(dataObject)
}
}
app.post(endpoint2, function(req,res){
request(HaloAPI + endpoint2, function(error, res, body){
[store data from the response body into an
object to be sent to firebase endpoint 'user'.
This is a url for an image]
//This is a player's emblem
database + "/user/emblem".set(dataObject)
}
}
app.post(endpoint3, function(req,res){
request(HaloAPI + endpoint3, function(error, res, body){
[store data from the response body into an
object to be sent to firebase endpoint 'user'.
This is a url for an image]
//This is a player's Spartan portrait
database + "/user/spartanImage".set(dataObject)
}
}
I'm expecting the database to be updated all at the same time; however, that is not the case all the time. Usually when I click the button with the event listener attached endpoint 2 and 3 come in at the same time as the data from endpoint 1, but most of the time I only get data from only endpoint 2 or only endpoint 3. Eventually I stop getting the data from endpoint 2 and 3 all together. In fact, with this current setup I can see the endpoints user/emblem and user/spartanImage populate in the database console but then they are taken away as soon as they are added. This has been troubling me from the beginning of this project and I would really appreciate some insight from someone more experience in Firebase than myself. Below I will link my relevant code, thanks in advance for the help.
request.js is where the initial AJAX calls are made client-side:
$searchButton.on("click", function(event){
event.preventDefault();
// the value of the search field creates the request object
// it is just a user's Xbox Live Gamertag and is used for the
// the subsequent requests.
var $search = $("#searchField").val();
$.post(homeRoute + "statSearch", {search: $search}, function(data){
console.log(data)
});
firebase.database().ref().on("value", function(snapshot){
function ez(path){
return snapshot.child(path).val();
}
var dataObject = {
gamertag: ez("gamertag"),
totalKills: ez("totalKills"),
totalDeaths: ez("totalDeaths"),
totalGames: ez("totalGames")
};
console.log(dataObject)
});
$.post(homeRoute + "emblemSearch", {search: $search}, function(data){
console.log(data)
});
$.post(homeRoute + "spartanSearch", {search: $search}, function(data){
console.log(data)
});
From there we go over to app.js my express server to make GET requests to the Halo Waypoint API and send the response formatted with the data I want to firebase:
app.post("/statSearch", function(req, res){
var search = req.body.search;
var statsOptions = new Options("https://www.haloapi.com/stats/h5/servicerecords/warzone?players="+search);
request(statsOptions, function (error, response, body) {
if (error) throw new Error(error);
var body = JSON.parse(response.body)
var playerData = {
gamertag: body.Results[0].Id,
totalKills: body.Results[0].Result.WarzoneStat.TotalKills,
totalDeaths: body.Results[0].Result.WarzoneStat.TotalDeaths,
totalGames: body.Results[0].Result.WarzoneStat.TotalGamesCompleted
};
res.send(playerData)
var userRef = ref.child("user");
// sending off the data object to Firebase at the "user" endpoint
userRef.set(playerData);
});
});
//emblem
app.post("/emblemSearch", function(req, res){
var search = req.body.search;
var imgOptions = new Options('https://www.haloapi.com/profile/h5/profiles/'+search+'/emblem', '512');
request(imgOptions, function (error, response, body) {
if (error) throw new Error(error);
var imgString = response.request.uri.href;
res.send(imgString);
var emblemRef = ref.child("user/emblem");
// sending off the url to Firebase at the endpoint "user/emblem"
emblemRef.set(imgString);
});
});
//spartan image
app.post("/spartanSearch", function(req, res){
var search = req.body.search
var spartanOptions = new Options('https://www.haloapi.com/profile/h5/profiles/'+search+'/spartan', '256');
request(spartanOptions, function (error, response, body) {
if (error) throw new Error(error);
var imgString = response.request.uri.href;
res.send(imgString);
var spartanImage = ref.child("user/spartanImage");
// doing the same as emblem to this endpoint^^^^
spartanImage.set(imgString);
});
});

Unable to get data from REST Calls using Node.js

I am making a REST API call from my php and Node.js application to a particular URL provided by the client which returns a Json object. It works fine from with the PHP. However, I am unable to receive data from my node application? What might be the possible reason can someone help me ?
Note: I have pasted a dummy REST URI for security reasons
It works fine with PHP infact i get the json formatted data in like couple of seconds.
$response =
file_get_contents('http://xyz.net/v2_resmgr/providers/pools'); echo
$response;
I try the same url using node.js i get a TimeOut error. I also tried setting the timeout but it would still not work.
var job = new CronJob({
cronTime: '0 */3 * * * *',
onTick: function () {
url= "http://xyznet/v2_resmgr/providers/pools";
var request = http.get(url, function (response) {
var buffer = "",
data,
route;
response.on("data", function (chunk) {
buffer += chunk;
});
response.on("end", function (err) {
console.log(buffer);
});
request.setTimeout( 200000, function( ) {
// handle timeout here
console.log("Time Out call to the Rest API");
});
});
},
start: true
});
job.start();
I don't know if this is the answer you are looking for, but life gets easier when you use the 'request' package (https://www.npmjs.org/package/request)
Here is what the code would look like using the request module:
var request = require('request');
request('http://xyznet/v2_resmgr/providers/pools', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // Print the body of the response.
}
})
Update: I coded something a little closer to your post. The code below does not use the "request" module and it contacts the server every 3 seconds.
setInterval(function () {
http.get('http://echo.jsontest.com/key/value', function (response) {
var responseBody = '';
response.on('data', function (chunk) {
responseBody += chunk;
});
response.on('end', function () {
console.log(responseBody);
var object = JSON.parse(responseBody)
});
});
}, 3000);

What is the best way to determine Tomcat has started with node.js

I am building an application using node.js and that application communicates with a Tomcat server. While the tomcat server is launching, I am not sure if Tomcat is ready and has come up or not, for now I use CURL and WGET on Windows and Mac with a timeout of 2 seconds to keep checking if localhost:8080 has come up.
Is there a better way to do this without relying on CURL and WGET?
The suggested way is to create a heartbeat service on the tomcat application (I.E. a simple service that sends OK when it's up), and poll that every x seconds.
A heartbeat service is essential for monitoring while the application is running, and there are also times when the application isn't ready even though it's already listening on the port (because there is some heavy initialization going on).
There are other ways though, if you're on the same server, you can tail the catalina.out until you receive "server started" line.
You can setup your tomcat application to notify your server that it's up (though that means the tomcat needs to know the url for the node.js server), or alternatively setup some kind of message queue (like ApacheMq or such) that you can register when the tomcat is up, this will also allow push messages between the two services.
You could implement a httpWatcher (mimicking the contract of file watcher - fs.watch). It could poll an http endpoint (a status route or html file) and would fire a callback when a 200 is returned (or when a max runs has been reached). Something like this:
var request = require('request');
var watch = function(uri) {
var options;
var callback;
if ('object' == typeof arguments[1]) {
options = arguments[1];
callback = arguments[2];
} else {
options = {};
callback = arguments[1];
}
if (options.interval === undefined) options.interval = 2000;
if (options.maxRuns === undefined) options.maxRuns = 10;
var runCount = 0;
var intervalId = setInterval(function() {
runCount++;
if(runCount > options.maxRuns) {
clearInterval(intervalId);
callback(null, false);
}
request(uri, function (error, response, body) {
if (!error && response.statusCode == 200) {
clearInterval(intervalId);
callback(null, true);
}
});
}, options.interval);
}
Then use it like so:
watch('http://blah.asdfasdfasdfasdfasdfs.com/', function(err, isGood) {
if (!err) {
console.log(isGood);
}
});
Or pass in options...
watch('http://www.google.com/', {interval:1000,maxRuns:3},
function(err, isGood) {
if (!err) {
console.log(isGood);
}
});
Well, you can make requests from Node.JS app:
var http = require("http");
var options = {
host: "example.com",
port: 80,
path: "/foo.html"
};
http.get(options, function(resp){
var data = "";
resp.on("data", function(chunk){
data += chunk;
});
resp.on("end", function() {
console.log(data);
// do something with data
});
}).on("error", function(e){
// HANDLE ERRORS
console.log("Got error: " + e.message);
}).on("socket", function(socket) {
// ADD TIMEOUT
socket.setTimeout(2000);
socket.on("timeout", function() {
req.abort();
// or make the request one more time
});
});
Documentation:
http://nodejs.org/docs/v0.4.11/api/http.html#http.request

Creating a map of ids to sockets and vice versa in Node.js

I'm trying to manage a bunch of socket connections. My app is basically an http server that receives posts and passes these along to a socket. When clients open a socket connection, they send a connect message with an id:
{"m":"connect","id":"1"}
The app then saves this id and socket in the id2socket and socket2id maps. On disconnect, the socket/id pair is deleted from the maps.
A post will also contain an id, which indicates the post data should be sent to the socket with that id.
That's great, and this works fine for a single open socket. However, when I have more than one socket open, and then I close a socket, that disconnect wipes everything from the map. I think my understanding of sockets in node is incomplete- is there only a single socket object that is used in the callback? Is there a better way to manage my open socket connections and ids?
start server:
>>node server.js
TCP server listening on 127.0.0.1:5280
HTTP server listening on 127.0.0.1:9002
telnet in:
>>telnet localhost 5280
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
{"m":"connect","id":"123"}
{"m":"connect","id":"123","success":"true"}
server after connection:
>>Connection from 127.0.0.1:57572
received data: {"m":"connect","id":"123"}
id: 1
m: connect
associating uid 1 with socket [object Object]
do a post:
python post.py {"foo":"bar"}
So this works fine for several open sockets (as long as 1 device is id 123, server has this hardwired for now). However, as soon as you close one connection all the socket connections are removed from the map.
Here's my code:
python script to do post:
import sys
import json
import httplib, urllib, urllib2
values = json.loads('{"foo":"bar"}')
headers = {"Content-type": "application/json"}
conn = httplib.HTTPConnection('127.0.0.1', 9002)
headers = {"Content-type": "application/json"}
conn.request("POST", "", json.dumps(values), headers)
response = conn.getresponse()
print "response.status: "+response.status
print "response.reason: "+response.reason
print "response.read: "+response.read()
conn.close()
node server (http and tcp), hardwired to send data to device '123' on post:
var net = require('net'); // tcp-server
var http = require("http"); // http-server
var qs = require('querystring'); // http-post
// Map of sockets to devices
var id2socket = new Object;
var socket2id = new Object;
// Setup a tcp server
var server_plug = net.createServer(function(socket) {
// Event handlers
socket.addListener("connect", function(conn) {
console.log("Connection from " + socket.remoteAddress + ":" + socket.remotePort );
});
socket.addListener("data", function(data) {
console.log("received data: " + data);
try {
request = JSON.parse(data);
response = request;
if(request.m !== undefined && request['id'] !== undefined){ // hack on 'id', id is js obj property
console.log("id: "+request['id']);
console.log("m: "+request.m);
if(request.m == 'connect'){
console.log("associating uid " + request['id'] + " with socket " + socket);
id2socket[request['id']] = socket;
socket2id[socket] = request['id'];
response.success = 'true';
} else {
response.success = 'true';
}
}
socket.write(JSON.stringify(response));
} catch (SyntaxError) {
console.log('Invalid JSON:' + data);
socket.write('{"success":"false","response":"invalid JSON"}');
}
});
socket.on('end', function() {
id = socket2id[socket]
console.log("socket disconnect by id " + id);
// wipe out the stored info
console.log("removing from map socket:"+socket+" id:"+id);
delete id2socket[id];
delete socket2id[socket];
});
socket.on('timeout', function() {
console.log('socket timeout');
});
});
// Setup http server
var server_http = http.createServer(
// Function to handle http:post requests, need two parts to it
// http://jnjnjn.com/113/node-js-for-noobs-grabbing-post-content/
function onRequest(request, response) {
request.setEncoding("utf8");
request.addListener("data", function(chunk) {
request.content += chunk;
});
request.addListener("end", function() {
console.log("post received!");
//console.log("Request received: "+request.content);
if (request.method == 'POST') {
//var json = qs.parse(request.content);
//console.log("Post: "+json);
// HACK TO TEST STUFF:
// send a message to one of the open sockets
try {
var socket = id2socket['123']; //hardwired
socket.write('{"m":"post"}');
} catch (Error) {
console.log("Cannot find socket with id "+'123');
}
}
});
}
);
// Fire up the servers
var HOST = '127.0.0.1';
var PORT = 5280;
var PORT2 = 9002;
server_plug.listen(PORT, HOST);
console.log("TCP server listening on "+HOST+":"+PORT);
server_http.listen(PORT2);
console.log("HTTP server listening on "+HOST+":"+PORT2);
Objects only take strings as keys for their properties. As your log shows, a socket object is converted into the string "[object Object]". As a result, socket #2 overwrites the id from socket #1 in the object, because all sockets are converted into the same string key. So, there is only one property in the object at all times, because all sockets come down to the same key. When you try to remove the id for socket #2, the single property is deleted and the object is empty.
You seem to want a custom property for each separate socket when used as a key. You can use WeakMaps for this. WeakMaps do allow objects as keys (as opposed to string-only keys), but as they're relatively new they may contain bugs at the moment.
(Note that the id2socket map can just be a plain object, because numbers are converted into strings just fine, and each number has its own, distinct string representation*.)
Using WeakMaps is as follows:
var socket2id = new WeakMap; // as if you were doing: var socket2id = {};
socket2id.set(socket, id); // as if you were doing: socket2id[socket] = id;
socket2id.get(socket); // as if you were doing: socket2id[socket];
socket2id.delete(socket); // as if you were doing: delete socket2id[socket];
Make sure to run with node --harmony (>= 0.7) or node --harmony_weakmaps (<= 0.6).
* 0 and -0 are exceptions, but you shouldn't be using -0 anyway because 0 === -0, so it's difficult to differ between them.

Categories

Resources