Enter twice in socket.on event - node.js

I'm new to Angular and Node.js.
My code executes a socket.emit to a server side function and receives a response in the socket.on event ('listartists').
Unfortunately, he enters twice in this event and I do not understand why.
On the server side (app.js) I put logs and the function is called correctly once, but then it goes through the socket.on twice ('listartists').
Thank you all
var appAng = angular.module('appAng', []).controller('myCtrl', function($scope) {
socket.on('listartists', function(msg) {
// !!! enter twice this part of the code
var ClientMessage = JSON.parse(msg);
if (ClientMessage.ClientID == GetClientUniqueId()) {
var artistslist = JSON.parse(ClientMessage.Message);
$scope.$apply(function() {
var artistslist=JSON.parse(ClientMessage.Message);
$scope.artists = artistslist;
});
}
});
});

i modified my code as :
socket.on('listartists', function(msg){
var ClientMessage=JSON.parse(msg);
if (ClientMessage.ClientID== GetClientUniqueId())
{
console.log("Arriva Lista Artisti " + ClientMessage.ClientID);
var artistslist =JSON.parse(ClientMessage.Message);
$scope.artists = artistslist;
$scope.$apply( function(){});
}
});
Anyway if i remove $scope.$apply( function(){}); the socket.on event is called only once,
otherwise it passes twice from there.
I think the problem is the management of the SCOPE some idea?

Related

Cannot broadcast message to specific room? TypeError: Cannot call method 'in' of undefined

I am pretty new to socket.io. I try to send a message between client and server by using socket.io. I want the server to broadcast the message to a specific room but I am not success to do so. The error is that " Missing error handler on socket. TypeError: Cannot call method 'in' of undefined". I try to simplify my code so to just input room ID like in the following code, room of 123 but I still got the same error.
Server side's code:
//For checking the username and display registered user
client.on("join",function(name){
clients.push(client);
console.log("Join Event Successfully");
});
//Create Room on server side
client.on("createRoom", function(name) {
console.log(name);
client.join(name);
console.log("Room Create Successfully");
console.log("Room "+ name);
console.log("Room create successfully");
});
//Join room event
client.on("joinRoom",function(room_id){
client.join(room_id);
console.log("Room Join Successfully");
});
//Socket uses to sync video in real time
//On playing event from one client and need to brocast inside the room
client.on("onPlay",function(data){
io.to('123').emit("onPlay_server",data);
console.log("onPlay event trigger");
});
//Socket uses to sync video in real time
//On Pause event from one client and need to brocast inside the room
client.on("onPuase",function(data){
io.to('123').emit("onPuase_server",data);
console.log("onPause event trigger");
});
// Event trigger when client disconnect from the sever
client.on("disconnect", function() {
console.log("There is someone left the room"+ toString(client.id));
});
Client's side code:
socketIO.on("onPause_server", function(currentTime){
console.log("onPause_server");
if(player_state === 'play'){
console.log("onPause_server");
player.pauseVideo();
Player.seektTo(currentTime);
player_state = 'pause'
}
Player.seektTo(currentTime);
});
//Get message from sever side on play message
socketIO.on("onPlay_server", function(currentTime){
console.log("onPlay_server event trigger");
if(player_state === 'pause'){
console.log("onPlay_server event trigger");
player.seekTo(currentTime);
Player.playVideo();
Player_state = "play";
}
player.seekTo(currentTime);
});
function onPlayerStateChange(event) {
//console.log(player.getCurrentTime());
if (event.data == YT.PlayerState.PAUSED) {
player.pauseVideo();
var currentTime = player.getCurrentTime();
player.seekTo(currentTime);
socketIO.emit("onPause",currentTime);
player_state = "paused";
}
else if (event.data == YT.PlayerState.PLAYING) {
player.playVideo();
var currentTime = player.getCurrentTime();
socketIO.emit("onPlay",currentTime);
player_state = "play";
}
}
The code is running fine until when client tries to send the message "onPlay" or "onPause" to the server side, the server immediately yields the error of " Missing error handler on socket. TypeError: Cannot call method 'in' of undefined"

Possible scoping issue

A possible node.js/backbone.js/socket.io scoping issue I can't wrap my head around.
(snippet from) server.js
var app = express();
var server = http.createServer(app);
io = io.listen(server);
(snippet from) index.html
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect(window.location.origin);
</script>
(snippet from) js/views/map.js
(function() { // self invoking anonymous function so we are able to
// create the private variable "map" that can be shared here
var map;
var webSocket = window.socket;
window.MapView = Backbone.View.extend({
initialize: function() {
this.render();
webSocket.on("marker dropped", this.propNewMarker);
},
events: {
"click .dropmarker" : "dropMarker"
},
dropMarker: function(event) {
console.log("This fires!!!");
webSocket.emit('marker dropped', { my: 'data' });
},
propNewMarker: function() {
console.log("someone dropped a marker (im in map.js)");
},
(snippet from) MapView.html
Drop marker
Behavior I am going for
Clicking on the "dropmarker" button in MapView.html should instigate the webSocket.emit action in dropMarker. (it fires off the console.log without any problems)
Tested
When I add
io.sockets.emit('marker dropped', { 'message': 'ello wurldz' });
into server.js, the propNewMarker function in map.js is fired correctly.
Preliminary conclusion
It seems that I am struggling with a scoping issue at the level of the buttonclick.
I'm not able to fire a websocket event there.
Any thoughts ? or should I offer more insights in the code before this can be debugged? (tried to keep it as clean as possible)
This doesn't look like an issue with the scope but in fact how you are using the socket
In order for propNewMarker to be called the server must emit a message on marker dropped
On the server if you add
io.sockets.on('connection', function (socket) {
socket.on('marker dropped',function(msg){
socket.emit('marker dropped',msg);
});
});
Then the client should respond just fine to the event. I did some testing and it looks like your scoping is just fine.

No blocking operation in MongoJS

I have to do an operation that calculate for me something, but I can't use the result of it, because I always stay in a wait state, in fact in my terminal remains in execution my program until I enter ctrl+C.
I have a main in nodejs for my program where I need to use my result calculated in a module.
var myJSONClient = {
"nombre" : "<nombre_cliente>",
"intervalo" : [0,0]
};
var intervalo = gestionar.gestion(myJSONClient,vector_intervalo);
console.log("intervalo: "+intervalo); //return undefined
And this is the module
var gestion = function(myJSON,vector_intervalo) {
var dburl = 'localhost/mongoapp';
var collection = ['clientes'];
var db = require('mongojs').connect(dburl, collection );
var intervalo_final;
function cliente(nombre, intervalo){
this.nombre = nombre;
this.intervalo = intervalo;
}
var cliente1 = new cliente(myJSON.nombre,myJSON.intervalo);
db.clientes.save(cliente1, function(err, saveCliente){
if (err || !saveCliente) console.log("Client "+cliente1.nombre+" not saved Error: "+err);
else console.log("Client "+saveCliente.nombre+" saved");
intervalo_final = calculate(vector_intervalo);
console.log(intervalo_final); //here I can see the right content of the variable intervalo_final
});
console.log(intervalo_final); //this is not executed
return intervalo_final;
}
exports.gestion = gestion;
Welcome to the async world! :)
First of all, you aren't doing blocking operations in Node. Actually, networking in Node is fully asynchronous.
The part you state the console.log works it's because the callback function of the db.clientes.save call. That callback states your mongo save has finished.
What asynchronous networking means?
It means that your save will be processed sometime in the future. The script will not wait for the response to continue the code. The console.log right after the save call will be executed soon as it's reached.
As for the "wait state" of your script, that it never ends, you should take a look at this question. There's the answer.

socket.io data seems to be sent multiple times(nodejs and craftyjs)

I am following this tutorial on making HTML5 games. I wanted to try and mix node in to make it multiplayer. I am using node.js(v0.10.4) on server and crafty.js on front end.
I am using socket.io to send and receive messages. For now it's just me(not multiple clients). The weird thing that happens is that the message that comes from the server seems to be sent multiple times. I turned on debug mode in socket.io but it only seems to be sending the data once, yet on the front end the data seems to be coming in, in multiples. I set an incrementor on the data and it seems as if the incrementor is not incrementing multiple times but instead I am getting multiple copies of the same data.
here's node code:
var http = require('http').createServer(handler),
static = require('node-static'),
io = require('socket.io').listen(http);
io.set('log level', 3);
http.listen(80);
//attach the socket to our server
var file = new static.Server(); //Create a file object so we can server the files in the correct folder
function handler(req, res) {
req.addListener('end', function() {
file.serve(req, res);
}).resume();
}
io.sockets.on('connection', function (socket) { //listen for any sockets that will come from the client
socket.on('collected', function(data) {
/**** here's where the data is being sent back to the client *****/
socket.emit('messageFromServer', { data: data.number });
});
});
and here's front end code:
//messenger entity
Crafty.c('SendRecieveMessages',{
count: 0,
sendMessageToServer : function() {
console.log('got a village');
/**** Here's where we send the message to the server ****/
socket.emit('collected', { village : "The message went to the server and back. it's collected", number : this.count });
this.count++;
},
recieveMessageFromServer : function() {
socket.on('messageFromServer', function(data) {
/*** This data seems to be coming back or logging multiple times? ***/
console.log(data);
});
}
});
Lastly here's a screenshot of the debug in process. As you can see number is not always incrementing, it almost looks like the data is getting stored. Thanks!
http://cl.ly/image/0i3H0q2P1X0S
It looks like every time you call Crafty.c, recieveMessageFromServer() is getting called too. Every time recieveMessageFromServer is invoked, it attaches an additional event listener on the socket. That's why the first time data comes back you get one copy, then the second time you get two, the third time you get three, and so on.
You either need to prevent recieveMessageFromServer from being called multiple times, or use removeListener or removeAllListeners to remove the previously attached listeners.
Thanks to #Bret Copeland for helping me figure this one out. As he pointed out, every time socket.on() is called, it seems to add another listener. To prevent this...
I declared a global variable:
I declared a variable as a property in my Game object(in craftyjs, so use whatever you want in your setup)
Game = {
//lots of other code here...
//need this to use later for socket.io
send_message : true
}
then edited my recieveMessageFromServer() function to check whether its ok to send the message or not:
recieveMessageFromServer : function() {
console.log('does this show up multiple times?');
/* Check whether the send_message is true before sending */
if (Game.send_message) {
socket.on('messageFromServer', function(data) {
console.log(data);
Game.send_message = false;
});
}
}

ClientJade - Trouble executing jade.render()

I've run into a problem in the clientside code for a Node.js app I'm working on.
The idea behind this is to update the browser immediately as the socket receives an event.
This is the script block on the client side:
script(src='/scripts/jadeTemplate.js')
script(src='/socket.io/socket.io.js')
script(type='text/javascript')
var socket = io.connect();
socket.on('obj', function(obj) {
var newsItem = document.createElement("item");
jade.render(newsItem, 'objTemplate', { object: obj });
$('#newsfeed').prepend(newsItem);
alert(obj);
});
When the alert() is placed before the jade.render(), it alerts, but if inserted after, it doesn't execute (hence, I think it's a problem with the jade.render()).
This is objTemplate.jade, referred to in line 7:
p #{object}
// That's it.
And this is a relevant snippet from the app.js:
var server = dgram.createSocket('udp4');
server.bind(41234);
server.on('message', function(buf, rinfo) {
isOnline = true;
var message = buf.toString();
io.sockets.emit('obj', message);
});
UPDATE:
Here's a link to /public/scripts/jadeTemplate.js, which IMO is too long of a snippet for a question.
If I need to provide any more snippets or files let me know. :)
Your template doesn't want an attribute object, it wants obj. Try this:
socket.on('obj', function(obj) {
var newsItem = document.createElement("item");
jade.render(newsItem, 'objTemplate', { obj: obj }); // changed object to obj
$('#newsfeed').prepend(newsItem);
alert(obj);
});
http://jsfiddle.net/trevordixon/VeYBY/ shows it working. If you change the attribute back to object, you'll get a javascript error in the console.

Resources